Как удалить повторяющиеся значения из многомерного массива в PHP

Как удалить повторяющиеся значения из многомерного массива в PHP?

пример массива:

Array
(
    [0] => Array
    (
        [0] => abc
        [1] => def
    )

    [1] => Array
    (
        [0] => ghi
        [1] => jkl
    )

    [2] => Array
    (
        [0] => mno
        [1] => pql
    )

    [3] => Array
    (
        [0] => abc
        [1] => def
    )

    [4] => Array
    (
        [0] => ghi
        [1] => jkl
    )

    [5] => Array
    (
        [0] => mno
        [1] => pql
    )

)

17 ответов


вот другой способ. Промежуточные переменные не сохраняются.

мы использовали это для удаления дубликатов результатов из различных перекрывающихся запросов.

$input = array_map("unserialize", array_unique(array_map("serialize", $input)));

С 5.2.9 вы можете использовать array_unique() если вы используете SORT_REGULAR флаг вот так:

array_unique($array, SORT_REGULAR);

это делает функцию сравнить элементы для равенства, как если бы $a == $b использовались, что идеально подходит для вашего случая.

выход

Array
(
    [0] => Array
        (
            [0] => abc
            [1] => def
        )

    [1] => Array
        (
            [0] => ghi
            [1] => jkl
        )

    [2] => Array
        (
            [0] => mno
            [1] => pql
        )

)

имейте в виду, однако, что документация гласит:

array_unique() не предназначен для работы с многомерными массивами.


У меня была аналогичная проблема, но я нашел для нее 100% рабочее решение.

<?php
    function super_unique($array,$key)
    {
       $temp_array = [];
       foreach ($array as &$v) {
           if (!isset($temp_array[$v[$key]]))
           $temp_array[$v[$key]] =& $v;
       }
       $array = array_values($temp_array);
       return $array;

    }


$arr="";
$arr[0]['id']=0;
$arr[0]['titel']="ABC";
$arr[1]['id']=1;
$arr[1]['titel']="DEF";
$arr[2]['id']=2;
$arr[2]['titel']="ABC";
$arr[3]['id']=3;
$arr[3]['titel']="XYZ";

echo "<pre>";
print_r($arr);
echo "unique*********************<br/>";
print_r(super_unique($arr,'titel'));

?>

другой путь. Сохранит ключи также.

function array_unique_multidimensional($input)
{
    $serialized = array_map('serialize', $input);
    $unique = array_unique($serialized);
    return array_intersect_key($input, $unique);
}

пользователь комментирует array_unique () документация есть много решений для этого. Вот один из них:--4-->

kenrbnsn в rbnsn точка com
27-Sep-2005 12: 09

еще один Array_Unique для multi-demensioned массивов. Я тестировал это только на двухочувствительных массивах, но его, вероятно, можно обобщить для большего количества или использовать рекурсию.

эта функция использует сериализацию, array_unique, и unserialize функции для выполнения работы.


function multi_unique($array) {
    foreach ($array as $k=>$na)
        $new[$k] = serialize($na);
    $uniq = array_unique($new);
    foreach($uniq as $k=>$ser)
        $new1[$k] = unserialize($ser);
    return ($new1);
}

Это из http://ca3.php.net/manual/en/function.array-unique.php#57202.


Если "удалить дубликаты" означает "удалить дубликаты, но пусть там", решением может быть применение array_unique(...) в колонке "идентификатор", а затем снять в исходном массиве все ключи, которые были удалены из массива столбцов:

$array = [
    [
        'id' => '123',
        'foo' => 'aaa',
        'bar' => 'bbb'
    ],
    [
        'id' => '123',
        'foo' => 'ccc',
        'bar' => 'ddd'
    ],
    [
        'id' => '567',
        'foo' => 'eee',
        'bar' => 'fff'
    ]
];

$ids = array_column($array, 'id');
$ids = array_unique($ids);
$array = array_filter($array, function ($key, $value) use ($ids) {
    return in_array($value, array_keys($ids));
}, ARRAY_FILTER_USE_BOTH);

результат:

Array
(
    [0] => Array
        (
            [id] => 123
            [foo] => aaa
            [bar] => bbb
        )

    [2] => Array
        (
            [id] => 567
            [foo] => eee
            [bar] => fff
        )

)

просто используйте параметр SORT_REGULAR в качестве второго параметра.

$uniqueArray = array_unique($array, SORT_REGULAR);

Если вам нужно устранить дубликаты на определенных ключах, таких как идентификатор mysqli, вот простой funciton

function search_array_compact($data,$key){
    $compact = [];
    foreach($data as $row){
        if(!in_array($row[$key],$compact)){
            $compact[] = $row;
        }
    }
    return $compact;
}

Бонусные Баллы Вы можете передать массив ключей и добавить внешний foreach, но это будет 2x медленнее на дополнительный ключ.


Array
(
    [0] => Array
        (
            [id] => 1
            [name] => john
        )

    [1] => Array
        (
            [id] => 2
            [name] => smith
        )

    [2] => Array
        (
            [id] => 3
            [name] => john
        )

    [3] => Array
        (
            [id] => 4
            [name] => robert
        )

)

$temp = array_unique(array_column($array, 'name'));
$unique_arr = array_intersect_key($array, $temp);

это удалит дубликаты имен из массива. уникальный ключ


Если у вас есть массив, как это:

(users - это имя массива)

Array=>
 [0] => (array)
   'user' => 'john'
   'age' => '23'
 [1] => (array)
  'user' => 'jane'
  'age' => '20'
 [2]=> (array)
  'user' => 'john'
  'age' => '23'

и вы хотите удалить дубликаты...затем:

$serialized = array();
for ($i=0; $i < sizeof($users); $i++) { 
  $test = in_array($users['user'], $serialized);
    if ($test == false) {
      $serialized[] = $users['user'];
    }
 }

может быть решением: P


легко читаемое решение, вероятно, не самое эффективное:

function arrayUnique($myArray){
    if(!is_array($myArray))
        return $myArray;

    foreach ($myArray as &$myvalue){
        $myvalue=serialize($myvalue);
    }

    $myArray=array_unique($myArray);

    foreach ($myArray as &$myvalue){
        $myvalue=unserialize($myvalue);
    }

    return $myArray;

} 

многие спрашивали меня, как сделать уникальный многомерный массив. Я взял ссылку из вашего комментария, и это помогает мне.

прежде всего, спасибо @jeromegamez @daveilers за ваше решение. Но каждый раз, когда я дал ответ, они спросили меня, как это 'сериализации' и 'восстановить' работает. Вот почему я хочу поделиться с вами причиной этого, чтобы это помогло большему числу людей понять концепцию, стоящую за этим.

Я объясняю, почему мы используем 'serialize' и "unserialize" в шагах:

Шаг 1: преобразование многомерного массива в одномерный массив

чтобы преобразовать многомерный массив в одномерный массив, сначала создайте представление потока байтов всех элементов (включая вложенные массивы) внутри массива. функция serialize () может генерировать байтовое потоковое представление значения. Чтобы создать представление потока байтов всех элементов, вызовите функцию serialize () внутри array_map() функция как функция обратного вызова. Результатом будет одномерный массив независимо от того, сколько уровней имеет многомерный массив.

Шаг 2: Сделайте значения уникальными

чтобы сделать этот одномерный массив уникальным, используйте функцию array_unique ().

Шаг 3: верните его в многомерный массив

хотя массив теперь уникален, значения выглядят как представление потока байтов. Чтобы вернуть его обратно многомерный массив, используйте функцию unserialize ().

$input = array_map("unserialize", array_unique(array_map("serialize", $input)));

еще раз спасибо за все это.


очень простой и логичный способ унификации многомерного массива выглядит следующим образом,

если у вас есть массив, как это:

Array
(
    [Key1] => Array
        (
            [0] => Value1
            [1] => Value2
            [2] => Value1
            [3] => Value3
            [4] => Value1
        )
    [Key2] => Array
        (
            [0] => Value1
            [1] => Value2
            [2] => Value1
            [3] => Value3
            [4] => Value4
        )
)

использовать foreach чтобы решить эту проблему:

foreach($array as $k=>$v){
    $unique=array_unique($v);
    $array[$k]=$unique;
}

это даст вам следующий результат:

Array
(
    [Key1] => Array
        (
            [0] => Value1
            [1] => Value2
            [3] => Value3
        )
    [Key2] => Array
        (
            [0] => Value1
            [1] => Value2
            [3] => Value3
            [4] => Value4
        )
)

и если вы хотите изменить порядок ключей,

foreach($array as $k=>$v){
    $unique= array_values(array_unique($v));
    $array[$k]=$unique;
}

эта операция даст вам упорядоченные Ключевые значения, как это:

Array
(
    [Key1] => Array
        (
            [0] => Value1
            [1] => Value2
            [2] => Value3
        )
    [Key2] => Array
        (
            [0] => Value1
            [1] => Value2
            [2] => Value3
            [3] => Value4
        )
)

надеюсь, это все прояснит.


альтернатива сериализации и уникальности

$test = [
    ['abc','def'],
    ['ghi','jkl'],
    ['mno','pql'],
    ['abc','def'],
    ['ghi','jkl'],
    ['mno','pql'],
];

$result = array_reduce(
    $test,
    function($carry,$item){
        if(!in_array($item,$carry)) {
            array_push($carry,$item);
        }
        return $carry;
    },
    []
);

var_dump($result);

/*
 php unique.php
array(3) {
    [0] =>
        array(2) {
            [0] =>
                string(3) "abc"
            [1] =>
                string(3) "def"
        }
    [1] =>
        array(2) {
            [0] =>
                string(3) "ghi"
            [1] =>
                string(3) "jkl"
        }
    [2] =>
        array(2) {
              [0] =>
                  string(3) "mno"
              [1] =>
                  string(3) "pql"
        }
}

*/


если у вас есть массив такой

data = array
(
[0] => array
(
    [subject] => a
    [object] => c
),
[1] => array
(
    [subject] => b
    [object] => d
),
[2] => array
(
    [subject] => d
    [object] => b
),
[3] => array
(
    [subject] => d
    [object] => c
),
[4] => array
(
    [subject] => c
    [object] => a
),
[5] => array
(
    [subject] => c
    [object] => d
)
)

и вы хотите получить такие массивы:

data = array
(
[0] => array
(
    [subject] => a
    [object] => c
),
[1] => array
(
    [subject] => b
    [object] => d
),
[2] => array
(
    [subject] => d
    [object] => c
)
)

или

data = array
(
[0] => array
(
    [subject] => d
    [object] => b
),
[1] => array
(
    [subject] => c
    [object] => a
),
[2] => array
(
    [subject] => c
    [object] => d
)
)

следующий код может помочь

    $data1 = array();
    $data1 = $data;
    for($q=0;$q<count($data);$q++)
    {
            for($p=0;$p<count($data1);$p++)
            {
                    if (($data[$q]["subject"] == $data1[$p]["object"]) && ($data[$q]["object"] == $data1[$p]["subject"]))
                    {
                            $data1[$p]["subject"] = $data[$q]["subject"];
                            $data1[$p]["object"] = $data[$q]["object"];
                    }
            }
    }
    $data1 = array_values(array_map("unserialize", array_unique(array_map("serialize", $data1))));
    $data = $data1;

Я много думал над этой проблемой и определил, что оптимальное решение должно следовать двум правилам.

  1. для масштабируемости измените массив на месте; нет копирования в новый массив
  2. для исполнения, каждое сравнение должно быть сделано только один раз

имея это в виду и учитывая все причуды PHP, ниже приведено решение, которое я придумал. В отличие от некоторых других ответов, он имеет возможность удалять элементы на основе чего угодно раздел(ы) вы хотите. Входной массив предполагается цифровых клавиш.

$count_array = count($input);
for ($i = 0; $i < $count_array; $i++) {
    if (isset($input[$i])) {
        for ($j = $i+1; $j < $count_array; $j++) {
            if (isset($input[$j])) {
                //this is where you do your comparison for dupes
                if ($input[$i]['checksum'] == $input[$j]['checksum']) {
                    unset($input[$j]);
                }
            }
        }
    }
}

единственным недостатком является то, что ключи не в порядке, когда итерация завершается. Это не проблема, если вы впоследствии используете только циклы foreach, но если вам нужно использовать цикл for, вы можете поместить $input = array_values($input); после изменения нумерации ключей.


как говорят люди array_unique() очень медленно, Вот фрагмент, который я использую для одного уровня многомерного массива.

$serialized_array = array_map("serialize", $input);

foreach ($serialized_array as $key => $val) {
     $result[$val] = true;
}

$output = array_map("unserialize", (array_keys($result)));

ссылка первый пользователь внес Примечание array_unique() страница функции в php.net