web-dev-qa-db-ja.com

PHP比較配列

とにかく、何らかのループを実行するのではなく、組み込み関数を使用してPHPの配列を比較することはできますか?

$a1 = array(1,2,3);
$a2 = array(1,2,3);

if (array_are_same($a1, $a2)) {
    // code here
}

ところで、配列の値は常に同じ順序になるとは限りません。

27
Andy Morcam
if ( $a == $b ) {
    echo 'We are the same!'
}
36

2つの配列を比較して、等しい値(重複しているかどうか、考慮して型ジャグリング)を設定するには、両方向に array_diff() を使用します。

_!array_diff($a, $b) && !array_diff($b, $a);
_

両方の配列の値が同じ場合(型ジャグリング後)、TRUEが得られます。それ以外の場合はFALSE。例:

_function array_equal_values(array $a, array $b) {
    return !array_diff($a, $b) && !array_diff($b, $a);
}

array_equal_values([1], []);            # FALSE
array_equal_values([], [1]);            # FALSE
array_equal_values(['1'], [1]);         # TRUE
array_equal_values(['1'], [1, 1, '1']); # TRUE
_

この例が示すように、_array_diff_は配列キーを方程式から除外し、値の順序についても考慮せず、値が重複しているかどうかについても考慮しません。


複製が違いを生まなければならない場合、これはよりトリッキーになります。 「単純な」値に関する限り(文字列と整数値のみが機能します)、 array_count_values() が作用して、どの値がどのくらいの頻度で配列内にあるかに関する情報を収集します。この情報は_==_と簡単に比較できます:

_array_count_values($a) == array_count_values($b);
_

これは、両方の配列が同じ時間(タイプジャグリング後)同じ値を持つ場合、TRUEになります。それ以外の場合はFALSE。例:

_function array_equal_values(array $a, array $b) {
    return array_count_values($a) == array_count_values($b);
}

array_equal_values([2, 1], [1, 2]);           # TRUE
array_equal_values([2, 1, 2], [1, 2, 2]);     # TRUE
array_equal_values(['2', '2'], [2, '2.0']);   # FALSE
array_equal_values(['2.0', '2'], [2, '2.0']); # TRUE
_

これは、2つのアレイのカウントを最初に比較することでさらに最適化できます。これは、比較的安価であり、値の重複をカウントする際にほとんどのアレイを区別するクイックテストです。


これまでのところ、これらの例は文字列と整数値に部分的に限定されており、_array_diff_との厳密な比較も不可能です。より厳密な比較専用の _array_search_ です。したがって、値をキーに変換するだけで比較できるように、値をカウントおよびインデックス化する必要があります(_array_search_が行うように)。

これはもう少し作業です。ただし、最終的には比較は以前と同じです。

_$count($a) == $count($b);
_

違いを生むのは_$count_だけです:

_    $table = [];
    $count = function (array $array) use (&$table) {
        $exit   = (bool)$table;
        $result = [];
        foreach ($array as $value) {
            $key = array_search($value, $table, true);

            if (FALSE !== $key) {
                if (!isset($result[$key])) {
                    $result[$key] = 1;
                } else {
                    $result[$key]++;
                }
                continue;
            }

            if ($exit) {
                break;
            }

            $key          = count($table);
            $table[$key]  = $value;
            $result[$key] = 1;
        }

        return $result;
    };
_

これにより、値のテーブルが保持されるため、両方の配列で同じインデックスを使用できます。また、新しい値が発生した2番目の配列で最初に早く終了することも可能です。

この関数は、パラメーターを追加することでstrictコンテキストを追加することもできます。さらに、別のパラメーターを追加することで、重複の有無を検索できるようになります。完全な例:

_function array_equal_values(array $a, array $b, $strict = FALSE, $allow_duplicate_values = TRUE) {

    $add = (int)!$allow_duplicate_values;

    if ($add and count($a) !== count($b)) {
        return FALSE;
    }

    $table = [];
    $count = function (array $array) use (&$table, $add, $strict) {
        $exit   = (bool)$table;
        $result = [];
        foreach ($array as $value) {
            $key = array_search($value, $table, $strict);

            if (FALSE !== $key) {
                if (!isset($result[$key])) {
                    $result[$key] = 1;
                } else {
                    $result[$key] += $add;
                }
                continue;
            }

            if ($exit) {
                break;
            }

            $key          = count($table);
            $table[$key]  = $value;
            $result[$key] = 1;
        }

        return $result;
    };

    return $count($a) == $count($b);
}
_

使用例:

_array_equal_values(['2.0', '2', 2], ['2', '2.0', 2], TRUE);           # TRUE
array_equal_values(['2.0', '2', 2, 2], ['2', '2.0', 2], TRUE);        # TRUE
array_equal_values(['2.0', '2', 2, 2], ['2', '2.0', 2], TRUE, FALSE); # FALSE
array_equal_values(['2'], ['2'], TRUE, FALSE);                        # TRUE
array_equal_values([2], ['2', 2]);                                    # TRUE
array_equal_values([2], ['2', 2], FALSE);                             # TRUE
array_equal_values([2], ['2', 2], FALSE, TRUE);                       # FALSE
_
28
hakre

@Cleanshooter申し訳ありませんが、これはしないでください、それはすべきことです:(このコンテキストで言及されているarray_diffもそうです)

$a1 = array('one','two');
$a2 = array('one','two','three');

var_dump(count(array_diff($a1, $a2)) === 0); // returns TRUE

(注釈:関数で空を使用することはできません before PHP 5.5 ))この場合、配列は異なりますが結果は真です。

array_diff [...] array1から、他の配列には存在しないすべてのエントリを含む配列を返します。

array_diffarray_get_all_differencesのようなものであることを意味しません。計算する数学セットで説明します:

{'one','two'} \ {'one','two','three'} = {}

これは、最初のセットにある2番目のセットのすべての要素を除いた、最初のセットのすべての要素のようなものを意味します。そのため

var_dump(array_diff($a2, $a1));

計算する

array(1) { [2]=> string(5) "three" } 

結論は、2つの配列からすべての「差異」を取得するために「両方の方法」でarray_diffを実行する必要があるということです。

お役に立てれば :)

12
P.Scheit

また、この方法を試すことができます:

if(serialize($a1) == serialize($a2))
4
Murz

array_intersect() は、すべての共通値を含む配列を返します。

3
moonw

$a1 == $a2 - それのどこが悪いんだい?

3
Alex Martelli

ユーザーから配列を取得するか、配列値を入力します。sort関数を使用して、両方の配列をソートします。三項演算子を使用して確認してください。両方の配列が等しい場合、配列は等しくなりますが、そうでない場合は配列が等しくありません。ここにはループの繰り返しはありません。

sort($a1);
sort($a2);
echo (($a1==$a2) ? "arrays are equal" : "arrays are not equal");
1
CJ Ramki

任意の順序にすることができる配列値を比較するための迅速な方法...

_function arrays_are_same($array1, $array2) {
    sort($array1);
    sort($array2);
    return $array1==$array2;
}
_

だから...

_    $array1 = array('audio', 'video', 'image');
    $array2 = array('video', 'image', 'audio');
_

arrays_are_same($array1, $array2)TRUEを返します

1
chichilatte

ここでの解説からの結論:

配列値の比較(型ジャグリング後)および同じ順序のみ:

array_values($a1) == array_values($a2)

配列値が等しい(型ジャグリング後)、同じ順序であり、配列キーが同じで同じ順序である比較:

array_values($a1) == array_values($a2) && array_keys($a1) == array_keys($a2)
1
Tyron

交差数が両方のソース配列と同じであることを確認します

$intersections = array_intersect($a1, $a2);
$equality = (count($a1) == count($a2)) && (count($a2) == count($intersections)) ? true : false;
0
rcourtna

大きな配列配列(> 10k)内の配列を検索する場合、はるかに高速は直列化された配列を比較します(キャッシュに保存されます)。 URLを使用した作業の例:

/**
@return array
*/
function createCache()
{
    $cache = [];
    foreach ($this->listOfUrl() as $url => $args)
    {
        ksort($args);
        $cache['url'][$url] = $args;
        $cache['arr'][crc32(serialize($args))] = $url;
    }
    return $cache;
}

/**
@param array $args
@return string
*/
function searchUrl($args)
{
    ksort($params);
    $crc = crc32(serialize($params));        
    return isset($this->cache['arr'][$crc]) ? $this->cache['arr'][$crc] : NULL;                
} 

/**
@param string $url
@return array
*/
function searchArgs($url)
{
    return isset($this->cache['url'][$url]) ? $this->cache['url'][$url] : NULL;
}
0
revoke

キーを気にせず、値だけを気にする場合、これは値を比較し、重複が確実にカウントされるようにする最良の方法です。

$mag = '{"1":"1","2":"2","3":"3","4":"3"}';
$mag_evo = '1|2|3';

$test1 = array_values(json_decode($mag, true));
$test2 = array_values(explode('|', $mag_evo));

if($test1 == $test2) {
    echo 'true';
}

$ magの配列には3に等しい2つの値があるため、これは真にエコーしません。

これは、値とキーのみを重視し、重複を重視しない場合に最適です。 $ mag = '{"1": "1"、 "2": "2"、 "3": "3"、 "4": "3"}'; $ mag_evo = '1 | 2 | 3';

$test1 = json_decode($mag, true);
$test2 = explode('|', $mag_evo);

// There is no difference in either array.  
if(!array_diff($test1, $test2) && !array_diff($test2, $test1)) { 
    echo 'true';
}

すべての値が両方の配列で見つかったため、これはtrueを返しますが、前述のように、重複は気にしません。

0
Case

2つの配列の値を比較します。

$a = array(1,2,3);
$b = array(1,3,2);

if (array_diff($a, $b) || array_diff($b, $a)) {
    echo 'Not equal';
}else{
    echo 'Equal';
}
0
1Rhino