Подтвердить что ты не робот

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

4b9b3361

Ответ 1

Это потому, что array_unique сравнивает элементы, используя сравнение строк. Из docs:

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

Строковое представление массива - это просто слово 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

Вот как это работает:

  • Каждый элемент массива сериализуется. Эта будет уникальным на основе массива содержание.

  • Результаты этого выполняются через array_unique, поэтому только массивы с уникальными подписи остаются.

  • array_intersect_key будет ключи от уникальных предметов из карта/уникальная функция (поскольку ключи исходного массива сохранены) и pull их из исходного источника массив.

Ответ 2

array_unique() поддерживает только многомерные массивы в PHP 5.2.9 и выше.

Вместо этого вы можете создать хэш массива и проверить его на уникальность.

$hashes = array(); 

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

array_unique($hashes);

Ответ 3

Здесь улучшенная версия @ryeguy answer:

<?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 одинаковый.

Я столкнулся с этим API Google Адресов. Я сочетал результаты нескольких запросов с разными типами объектов (думаю теги). Но у меня есть дубликаты, так как объект может быть помещен в несколько категорий (типов). И метод с serialize не работал, так как attrs были разными, а именно photo_reference и reference. Вероятно, это похоже на временные идентификаторы.

Ответ 4

array_unique deosn't работает рекурсивно, поэтому он просто думает: "Это все Array s, пусть убивают всех, кроме одного... здесь мы идем!"

Ответ 5

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

  • Отличительные значения могут быть извлечены из массива PHP ассоциативных атрибутов, используя foreach
  • Это упрощенный подход

Подробный ответ

Контекст

  • PHP 5.3
  • Массив PHP ассоциативных массивов (переменная составных данных табуляции)
  • Альтернативное имя для этой составной переменной - ArrayOfDictionary (AOD)

Проблема

  • Сценарий: DeveloperMarsher имеет встроенную составную переменную PHP
    • DeveloperMarsher хочет извлечь отдельные значения в определенную пару имя-значение
    • В приведенном ниже примере DeveloperMarsher хочет получить строки для каждой отдельной пары fname name-value

Решение

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

Ловушки

  • Это решение не объединяется в поля, которые не являются частью операции DISTINCT.
  • Произвольные пары имени и имени возвращаются из произвольно выбранных строк
  • Произвольный порядок сортировки вывода
  • Произвольное обращение с почтовым ящиком (является ли капитал A отличным от нижнего регистра a?)

См. также

  • php array_intersect_key
  • php array_flip