web-dev-qa-db-fra.com

Comment supprimer les valeurs en double d'un tableau multidimensionnel dans PHP

Comment puis-je supprimer les valeurs en double d'un tableau multidimensionnel en PHP?

Exemple de tableau:

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
    )

)
284
Ian

Voici un autre moyen. Aucune variable intermédiaire n'est enregistrée.

Nous avons utilisé cela pour dédoubler les résultats d'une variété de requêtes se chevauchant.

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

Depuis la version 5.2.9, vous pouvez utiliser array_unique() si vous utilisez le drapeau SORT_REGULAR comme suit:

array_unique($array, SORT_REGULAR);

Cela rend la fonction comparer les éléments pour l’égalité comme si $a == $b était utilisé, ce qui est parfait pour votre cas.

Sortie

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

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

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

)

Gardez toutefois à l'esprit que la documentation indique:

array_unique() n'est pas destiné à fonctionner sur des tableaux multidimensionnels.

215
Ja͢ck

J'ai eu un problème similaire mais j'ai trouvé une solution efficace à 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'));

?>
58
Rajendrasinh

Autrement. Préserve les clés aussi.

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

Les commentaires de l'utilisateur sur la documentation array_unique () apportent de nombreuses solutions. Voici l'un d'entre eux:

kenrbnsn à rbnsn dot com
27 sept. 2005 12:09

Encore un autre Array_Unique pour les tableaux multi-tensions. Je n’ai testé cela que sur des tableaux à deux divisions, mais cela pourrait probablement être généralisé pour davantage, ou utiliser la récursion.

Cette fonction utilise les fonctions serialize, array_unique et unserialize pour effectuer le travail.


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

Ceci est de http://ca3.php.net/manual/en/function.array-unique.php#57202 .

20
Jeremy Ruten

Si "supprimer les doublons" signifie "supprimer les doublons, mais en laisser un", une solution pourrait consister à appliquer d'abord array_unique(...) sur la "colonne d'identificateur", puis à supprimer dans le tableau d'origine toutes les clés déjà utilisées. retiré du tableau de colonnes:

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

Le résultat est:

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

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

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

Cela supprimera les noms en double du tableau. unique par clé

8
Mahak Choudhary

si vous avez besoin d'éliminer les doublons sur des clés spécifiques, telles qu'un identifiant mysqli, voici une fonction simple

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

Points bonus Vous pouvez passer un tableau de clés et en ajouter une autre, mais ce sera 2 fois plus lent par clé supplémentaire.

3
r3wt

Utilisez simplement l'option SORT_REGULAR comme second paramètre.

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

si vous avez un tableau comme celui-ci:

(utilisateurs est le nom du tableau)

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

et vous voulez supprimer les doublons ... alors:

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

peut être une solution: P

2
Limon

Une solution facile à lire, probablement pas la plus efficace:

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

Voici un moyen très simple et logique de créer un tableau multi-dimensionnel comme suit:

Si vous avez un tableau comme celui-ci:

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

utilisez foreach pour résoudre ceci:

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

cela vous donnera le résultat suivant:

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

et si vous voulez réorganiser l'ordre des touches,

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

Cette opération vous donnera les valeurs clés arrangées comme ceci:

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

J'espère que ça va tout effacer.

1
Anand agrawal

Beaucoup de personnes m'ont demandé comment créer un tableau multidimensionnel unique. J'ai pris référence à votre commentaire et cela m'aide.

Tout d’abord, merci à @jeromegamez @daveilers pour votre solution. Mais chaque fois que j'ai donné la réponse, ils m'ont demandé comment cela fonctionne: "sérialiser" et "désérialiser". C'est pourquoi je veux partager la raison de ceci avec vous afin que cela aide plus de gens à comprendre le concept derrière tout cela.

J'explique pourquoi nous utilisons 'sérialiser' et 'désérialiser' par étapes:

Étape 1: convertissez le tableau multidimensionnel en tableau unidimensionnel

Pour convertir le tableau multidimensionnel en un tableau unidimensionnel, commencez par générer une représentation sous forme de flux d'octets de tous les éléments (y compris les tableaux imbriqués) à l'intérieur du tableau. La fonction serialize () peut générer une représentation sous forme de flux d'octets d'une valeur. Pour générer une représentation de flux d'octets de tous les éléments, appelez la fonction serialize () dans la fonction array_map () en tant que fonction de rappel. Le résultat sera un tableau unidimensionnel, quel que soit le nombre de niveaux du tableau multidimensionnel.

Étape 2: Rendre les valeurs uniques

Pour rendre ce tableau unidimensionnel unique, utilisez la fonction array_unique ().

Étape 3: revenez au tableau multidimensionnel

Bien que le tableau soit maintenant unique, les valeurs ressemblent à une représentation de flux d'octets. Pour revenir au tableau multidimensionnel, utilisez la fonction unserialize ().

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

Merci encore pour tout ça.

1
Manish

J'ai longuement réfléchi à ce problème et déterminé que la solution optimale devait suivre deux règles.

  1. Pour l'évolutivité, modifiez le tableau en place. pas de copie dans un nouveau tableau
  2. Pour la performance, chaque comparaison doit être faite qu'une seule fois

Dans cet esprit, et compte tenu de toutes les bizarreries de PHP, voici la solution que j'ai proposée. Contrairement à certaines des autres réponses, il est possible de supprimer des éléments en fonction de la ou des clés souhaitées. Le tableau en entrée devrait être composé de clés numériques.

$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]);
                }
            }
        }
    }
}

Le seul inconvénient est que les clés ne sont pas en ordre à la fin de l'itération. Ce n'est pas un problème si, par la suite, vous utilisez uniquement des boucles foreach, mais si vous devez utiliser une boucle for, vous pouvez mettre $input = array_values($input); après ce qui précède pour renuméroter les clés.

0
Snake

Si vous avez un tableau comme celui-ci

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

et vous voulez obtenir des tableaux comme celui-ci:

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

ou

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

un code suivant peut aider

    $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

Une alternative à la sérialisation et unique

$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é

Comme les gens disent que array_unique() est très lent, voici un extrait de code que j'utilise pour un tableau multidimensionnel à un niveau.

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

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

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

Note de référence du premier utilisateur ayant contribué à la note de array_unique()page de fonction dans php.net

0
Anuj