it-swarm.com.ru

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

)
277
Ian

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

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

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

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

209
Ja͢ck

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

?>
57
Rajendrasinh

По-другому. Сохранит и ключи.

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

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

kenrbnsn at 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 .

19
Jeremy Ruten

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

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

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

7
Mahak Choudhary

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

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

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

3
r3wt

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

$uniqueArray = array_unique($array, SORT_REGULAR);
3
anghazi ghermezi

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

(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

2
Limon

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

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;

} 
1
pixeline

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

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

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

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

1
Anand agrawal

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

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

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

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

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

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

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

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

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

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

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

1
Manish

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

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

0
Snake

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

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;
0
milic

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

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

* /

0
Denis Laliberté

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

0
Anuj