Thanh Trung
Thanh Trung

Reputation: 3804

PHP array unique by column

How to filter an array to give unique elements according to one or more columns. Example:

array(
    array('name'=>'toto', 'type'=>'1', 'type2'=> '2')
    array('name'=>'tata', 'type'=>'1', 'type2'=> '3')
    array('name'=>'titi', 'type'=>'1', 'type2'=> '2')
    array('name'=>'tutu', 'type'=>'2', 'type2'=> '4')
    array('name'=>'tete', 'type'=>'3', 'type2'=> '2')
)

If we choose type and type2 as the unique column. The result of the algorithm should gives

array(
    array('name'=>'toto', 'type'=>'1', 'type2'=> '2')
    array('name'=>'tata', 'type'=>'1', 'type2'=> '3')
    array('name'=>'tutu', 'type'=>'2', 'type2'=> '4')
    array('name'=>'tete', 'type'=>'3', 'type2'=> '2')
)

I can think of an algorithm by hashing the type concatenate with type2, store in a table and using isset to find the existence. But I'm not sure that's the best algorithm.

Upvotes: 4

Views: 4322

Answers (5)

lov3catch
lov3catch

Reputation: 141

What about this way?

Result array is not the same as that of the author. But still valid for the condition:

...filter an array to give unique elements according to one or more columns.

<?php

declare(strict_types=1);

$input = [
    ['name' => 'toto', 'type' => '1', 'type2' => '2'],
    ['name' => 'tata', 'type' => '1', 'type2' => '3'],
    ['name' => 'titi', 'type' => '1', 'type2' => '2'],
    ['name' => 'tutu', 'type' => '2', 'type2' => '4'],
    ['name' => 'tete', 'type' => '3', 'type2' => '2'],
];

$keys = array_map(
    static fn(string $key, string $value) => "$key:$value",
    array_column($input, 'type'), array_column($input, 'type2'));

$result = array_values(array_combine($keys, array_values($input)));

$expect = [
    ['name' => 'titi', 'type' => '1', 'type2' => '2'],
    ['name' => 'tata', 'type' => '1', 'type2' => '3'],
    ['name' => 'tutu', 'type' => '2', 'type2' => '4'],
    ['name' => 'tete', 'type' => '3', 'type2' => '2'],
];

assert($result === $expect); // true

Upvotes: 0

Baba
Baba

Reputation: 95101

All you need is

$data = array(
    array('name'=>'toto', 'type'=>'1', 'type2'=> '2'),
    array('name'=>'tata', 'type'=>'1', 'type2'=> '3'),
    array('name'=>'titi', 'type'=>'1', 'type2'=> '2'),
    array('name'=>'tutu', 'type'=>'2', 'type2'=> '4'),
    array('name'=>'tete', 'type'=>'3', 'type2'=> '2')
);


$tmp = array();
foreach($data as $v) {
    $id = $v['type'] . "|" . $v['type2'];
    isset($tmp[$id]) or $tmp[$id] = $v;
}
print_r(array_values($tmp));

Upvotes: 2

Atle
Atle

Reputation: 5457

Updated to support key combinations

<?php

$array=array(
    array('name'=>'toto', 'type'=>'1', 'type2'=> '2'),
    array('name'=>'tata', 'type'=>'1', 'type2'=> '3'),
    array('name'=>'titi', 'type'=>'1', 'type2'=> '2'),
    array('name'=>'tutu', 'type'=>'2', 'type2'=> '4'),
);

function filter($key,$array){
    $filtered=array();
    $used=array();
    foreach ($array as $e){
        $v=array();
        foreach ($key as $k) $v[]=$e[$k];
        if (!in_array($v,$used)){
            $used[]=$v;
            $filtered[]=$e;
        }
    }
    return $filtered;
}

$filtered=filter(array('type2','type'),$array);

Upvotes: 1

deceze
deceze

Reputation: 522042

$keys = array('type', 'type2');
$filtered = array();

foreach ($array as $elem) {
    $compKey = join('|', array_intersect_key($elem, array_flip($keys)));
    $filtered[$compKey] = $elem;
}

// optionally: $filtered = array_values($filtered);

Upvotes: 2

Tasso Evangelista
Tasso Evangelista

Reputation: 1632

$arr = array(
    array('name'=>'toto', 'type'=>'1', 'type2'=> '2'),
    array('name'=>'tata', 'type'=>'1', 'type2'=> '3'),
    array('name'=>'titi', 'type'=>'1', 'type2'=> '2'),
    array('name'=>'tutu', 'type'=>'2', 'type2'=> '4')
);

$filtered = array(); // resulting array
$combinations = array(); // combinations of 'type' and 'type2' values

foreach ( $arr as $elem ) {

    $comb = array($elem['type'], $elem['type2']);

    if ( !in_array($comb, $combinations) ) { // new combination
        $combinations[] = $comb;
        $filtered[] = $elem;
    }
}

Upvotes: 2

Related Questions