Как использовать array unique для массива массивов?

у меня есть массив

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 работает не так, как ожидалось?

5 ответов


потому что array_unique сравнивает элементы с помощью сравнения строк. От docs:

Примечание: рассматриваются два элемента равны, если и только если (string) $elem1 === (строка) $elem2. In words: когда строковое представление одно и то же. Будет использован первый элемент.

строковое представление массива-это просто слово 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 Places API. Я комбинировал результаты нескольких запросов с различными типами объектов (думаю, теги). Но я получил дубликаты, так как объект может быть помещен в несколько категорий (типов). И метод с serialize не работы, поскольку у attrs были разные, а именно:photo_reference и reference. Возможно, это временные удостоверения личности.


array_unique deosn не работает рекурсивно, поэтому он просто думает: "это все Arrays, давайте убьем всех, кроме одного... поехали!"


быстрый ответ (TL;DR)

  • различные значения могут быть извлечены из массива PHP AssociativeArrays с помощью foreach
  • это упрощенный подход

Подробный Ответ!--5-->

контекст

  • PHP 5.3
  • PHP массив AssociativeArrays (tabluar составная переменная данных)
  • альтернативным именем для этой составной переменной является ArrayOfDictionary (AOD)
  • сценарий: DeveloperMarsher имеет табличную составную переменную PHP
    • DeveloperMarsher хочет извлечь отдельные значения на конкретной паре имя-значение
    • в приведенном ниже примере DeveloperMarsher хочет получить строки для каждого отдельного fname пары имя-значение

решение

  • example01 ;; DeveloperMarsher начинает с переменной данных tabluar, которая выглядит следующим образом

    $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);
    
  • example01 ;; 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',
    ),
  ),
)

подводные камни

  • это решение не агрегируется на полях, которые не являются частью отдельной операции
  • произвольные пары имя-значение возвращаются из произвольно выбранных отдельные ряды
  • произвольный порядок сортировки вывода
  • произвольная обработка буквенного регистра (является ли капитал отличным от нижнего регистра a ?)

см. также

  • php array_intersect_key
  • php array_flip