Как удалить повторяющиеся значения из многомерного массива в PHP - PullRequest
277 голосов
/ 21 ноября 2008

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

1 голос
/ 19 января 2018

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

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

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 голос
/ 01 сентября 2016

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

Прежде всего, спасибо @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 голос
/ 19 июня 2009

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

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;

} 
0 голосов
/ 29 ноября 2014

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

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 голосов
/ 18 апреля 2015

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

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

  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 голосов
/ 07 ноября 2014

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

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

* /

...