Как удалить повторяющиеся значения из многомерного массива в 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
    )

)

Ответ 1

Вот еще один способ. Промежуточные переменные не сохраняются.

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

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

Ответ 2

Начиная с 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() не предназначен для работы с многомерными массивами.

Ответ 3

У меня была аналогичная проблема, но я нашел для нее 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'));

?>

Ответ 4

Другой способ. Также сохранит ключи.

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

Ответ 5

Комментарии пользователей к документации array_unique() имеют много решений. Вот один из них:

kenrbnsn в rbnsn dot com
27-сент.-2005 12:09

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

Эта функция использует функции serialize, 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.

Ответ 6

Если "удалить дубликаты" означает "удалить дубликаты, но пусть один там", решение может состоять в том, чтобы сначала применить 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
        )

)

Ответ 7

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);

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

Ответ 8

если вам нужно устранить дубликаты на определенных ключах, таких как id 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 медленнее за дополнительный ключ.

Ответ 9

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

$uniqueArray = array_unique($array, SORT_REGULAR);

Ответ 10

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

(пользователи - это имя массива)

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

Ответ 11

Легко читаемое решение, возможно, не самое эффективное:

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;

} 

Ответ 12

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

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

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

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

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

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

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

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

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

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

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

Ответ 13

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

Если у вас есть массив вроде этого:

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
        )
)

Надеюсь, все это очистит.

Ответ 14

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

$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"
        }
}

*/

Ответ 15

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

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;

Ответ 16

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

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

Учитывая это и учитывая все причуды 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); после этого, чтобы перенумеровать ключи.

Ответ 17

Как говорят люди, 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

Ответ 18

Простое решение:

array_unique($array, SORT_REGULAR)