配列の配列で array_unique を使用するにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/2561248

  •  23-09-2019
  •  | 
  •  

質問

配列があります

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 が期待どおりに動作しない理由はありますか?

役に立ちましたか?

解決

その理由は array_unique 文字列比較を使用して項目を比較します。から ドキュメント:

注記:次の 2 つの要素が考慮されます 等しい場合のみ (文字列) $elem 1 === (文字列) $elem 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_key かかります からの一意のアイテムのキー map/unique 関数 (ソース配列のキーが保持されるため) と pull それらを元のソースから取り除きます 配列。

他のヒント

array_unique()のみ多次元PHP 5.2.9における配列と高いがサポートされています。

その代わり、あなたは配列のハッシュを作成し、ユニークネスのためにそれを確認することができます。

$hashes = array(); 

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

array_unique($hashes);

ここで @ 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が同じであっても違うことができる属性

私は GoogleプレイスAPIするでそれに遭遇しました。私は、オブジェクトの異なるタイプのいくつかの要求の結果を組み合わせた(タグと思います)。オブジェクトはいくつかのカテゴリー(種類)に入れてすることができるので、しかし、私は、重複を得ました。 ATTRSは、すなわち、serializephoto_reference異なっていたのでreferenceと方法は、動作しませんでした。おそらく、これらは一時的なIDSのようなものです。

array_unique deosn't作業再帰的な、それだけで「これはすべてArrays、レッツ・キルすべてのですが、1つは...ここで行く!」

と思って

クイックアンサー (TL;DR)

  • foreach を使用して、AssociativeArray の PHP 配列から個別の値を抽出できます。
  • これは単純なアプローチです

詳細な回答

コンテクスト

  • PHP5.3
  • AssociativeArray の PHP 配列 (表形式の複合データ変数)
  • この複合変数の代替名は ArrayOfDictionary (AOD) です。

問題

  • シナリオ: DeveloperMarsher には PHP 表形式の複合変数があります
    • DeveloperMarsher は、特定の名前と値のペアから個別の値を抽出したいと考えています
    • 以下の例では、DeveloperMarsher は個別の行ごとに行を取得したいと考えています。 fname 名前と値のペア

解決

  • 例01 ;;DeveloperMarsher は、次のような表形式のデータ変数から始まります。

    $aodtable = json_decode('[
    {
      "fname": "homer"
      ,"lname": "simpson"
    },
    {
      "fname": "homer"
      ,"lname": "jackson"
    },
    {
      "fname": "homer"
      ,"lname": "johnson"
    },
    {
      "fname": "bart"
      ,"lname": "johnson"
    },
    {
      "fname": "bart"
      ,"lname": "jackson"
    },
    {
      "fname": "bart"
      ,"lname": "simpson"
    },
    {
      "fname": "fred"
      ,"lname": "flintstone"
    }
    ]',true);
    
  • 例01 ;;DeveloperMarsher は、表示された値を追跡する foreach ループを使用して個別の値を抽出できます

    $sgfield  =   'fname';
    $bgnocase =   true;
    
    //
    $targfield  =   $sgfield;
    $ddseen     =   Array();
    $vout       =   Array();
    foreach ($aodtable as $datarow) {
    if( (boolean) $bgnocase == true ){ @$datarow[$targfield] = @strtolower($datarow[$targfield]); }
    if( (string) @$ddseen[ $datarow[$targfield] ] == '' ){
      $rowout   = array_intersect_key($datarow, array_flip(array_keys($datarow)));
      $ddseen[ $datarow[$targfield] ] = $datarow[$targfield];
      $vout[] = Array( $rowout );
    }
    }
    //;;
    
    print var_export( $vout, true );
    

出力結果

array (
  0 =>
  array (
    0 =>
    array (
      'fname' => 'homer',
      'lname' => 'simpson',
    ),
  ),
  1 =>
  array (
    0 =>
    array (
      'fname' => 'bart',
      'lname' => 'johnson',
    ),
  ),
  2 =>
  array (
    0 =>
    array (
      'fname' => 'fred',
      'lname' => 'flintstone',
    ),
  ),
)

落とし穴

  • このソリューションは、DISTINCT 操作の一部ではないフィールドでは集計しません。
  • 任意の名前と値のペアが、任意に選択された個別の行から返されます。
  • 出力の任意のソート順序
  • 大文字と小文字の任意の処理 (大文字の A と小文字の A は区別されますか?)

こちらも参照

  • php array_intersect_key
  • php配列フリップ
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;
}

トリックをしないこと?

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top