21

私は配列を持っています

Array(
[0] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 3
        [frame_id] => 3
    )

[1] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 3
        [frame_id] => 3
    )

[2] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 8
        [frame_id] => 8
    )

[3] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 3
        [frame_id] => 3
    )

[4] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 3
        [frame_id] => 3
    )

)

ご覧のとおり、キー 0 は 1、3、4 と同じです。キー 2 はそれらすべてとは異なります。

それらに対してarray_unique関数を実行すると、残っているのは

Array (
[0] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 3
        [frame_id] => 3
    )
)

array_unique が期待どおりに機能しない理由はありますか?

4

7 に答える 7

80

array_unique文字列比較を使用してアイテムを比較するためです。ドキュメントから:

注: (文字列) $elem1 === (文字列) $elem2 の場合に限り、2 つの要素は等しいと見なされます。つまり、文字列表現が同じ場合です。最初の要素が使用されます。

配列の文字列表現は、Arrayその内容に関係なく、単なる単語です。

以下を使用して、やりたいことを実行できます。

$arr = array(
    array('user_id' => 33, 'frame_id' => 3),
    array('user_id' => 33, 'frame_id' => 3),
    array('user_id' => 33, 'frame_id' => 8)
);

$arr = array_intersect_key($arr, array_unique(array_map('serialize', $arr)));

//result:
array
  0 => 
    array
      'user_id' => int 33
      'user' => int 3
  2 => 
    array
      'user_id' => int 33
      'user' => int 8

仕組みは次のとおりです。

  1. 各配列項目はシリアル化されます。これは、配列の内容に基づいて一意になります。

  2. この結果は を通して実行されるarray_uniqueため、一意の署名を持つ配列のみが残ります。

  3. array_intersect_keymap/unique 関数から一意のアイテムのキーを取得し (ソース配列のキーが保持されるため)、元のソース配列からそれらを引き出します。

于 2010-04-01T14:53:49.933 に答える
5

@ryeguyの回答の改良版は次のとおりです。

<?php

$arr = array(
    array('user_id' => 33, 'tmp_id' => 3),
    array('user_id' => 33, 'tmp_id' => 4),
    array('user_id' => 33, 'tmp_id' => 5)
);


# $arr = array_intersect_key($arr, array_unique(array_map('serialize', $arr)));
$arr = array_intersect_key($arr, array_unique(array_map(function ($el) {
    return $el['user_id'];
}, $arr)));

//result:
array
  0 => 
    array
      'user_id' => int 33
      'tmp_id' => int 3

まず、不要なシリアル化を行いません。次に、id が同じであっても、属性が異なる場合があります。

ここでの秘訣はarray_unique()、キーを保持することです。

$ php -r 'var_dump(array_unique([1, 2, 2, 3]));'
array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [3]=>
  int(3)
}

array_intersect_key()これで、必要な要素を残しましょう。

Google Places APIで遭遇しました。いくつかのリクエストの結果をさまざまなタイプのオブジェクト (タグと考えてください) と組み合わせていました。しかし、オブジェクトは複数のカテゴリ (タイプ) に分類される可能性があるため、重複が発生しました。そして、 attrs が異なっていたため、つまりandを使用した方法はserialize機能しませんでした。おそらくこれらは一時的な ID のようなものです。photo_referencereference

于 2016-12-07T15:02:14.983 に答える
3

array_unique()PHP5.2.9以降では多次元配列のみをサポートします。

代わりに、配列のハッシュを作成して、一意性を確認できます。

$hashes = array(); 

foreach($array as $val) { 
    $hashes[md5(serialize($val))] = $val; 
} 

array_unique($hashes);
于 2010-04-01T14:56:44.040 に答える
2

array_unique deosn は再帰的に機能しないため、「これはすべてArrays です。1 つを除いてすべてを削除してみましょう...さあ、行きましょう!」と考えるだけです。

于 2010-04-01T14:54:38.547 に答える
1
function array_unique_recursive($array)
{
    $array = array_unique($array, SORT_REGULAR);

    foreach ($array as $key => $elem) {
        if (is_array($elem)) {
            $array[$key] = array_unique_recursive($elem);
        }
    }

    return $array;
}

それはトリックをしませんか?

于 2018-11-08T12:30:38.063 に答える