0

In case of one-dim array I can use array_unique to get unique entries. But which function should be used to work with two-dim arrays? For instance:

Array[0][0] = '123'; Array[0][1] = 'aaa';
Array[1][0] = '124'; Array[1][1] = 'aaa';
Array[2][0] = '124'; Array[2][1] = 'aaa';

In the above example I need to delete non-unique rows based on column 0. As a result I should get first two entries, while the third entry should be deleted. How to do this?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Gusgus
  • 353
  • 2
  • 6
  • 22
  • I don't think there is a built-in function for this, you may have to do this yourself with a `foreach`. – gen_Eric Jul 25 '12 at 13:34
  • see the User Contributed Notes on [`array_unique`](http://php.net/manual/en/function.array-unique.php#103195) – xkeshav Jul 25 '12 at 13:34
  • What exactly do you want the result to look like? – gen_Eric Jul 25 '12 at 13:36
  • If it's based purely on one "column" (second level key) which always contains a string or an int value, just iterate the array and create a new one where the root keys (the keys of the first level) are the value of that column. This results in an array where only the later elements with a given value in the specific column are left. You can pass the result through `array_values()` to 0-index it again. If you want the earlier values instead of the later ones, add an `isset()` check in the loop. But I'm not posting this as an answer because there are soooo many duplicates of this question. – DaveRandom Jul 25 '12 at 13:40

4 Answers4

2

Try this...

function unique_matrix($matrix) {
    $matrixAux = $matrix;

    foreach($matrix as $key => $subMatrix) {
        unset($matrixAux[$key]);

        foreach($matrixAux as $subMatrixAux) {
            if($subMatrix === $subMatrixAux) {
            // Or this
            //if($subMatrix[0] === $subMatrixAux[0]) {
                unset($matrix[$key]);
            }
        }
    }

    return $matrix;
}

$matrix = array(
    0 => array(0 => '123', 1 => 'aaa'),
    1 => array(0 => '124', 1 => 'aaa'),
    2 => array(0 => '124', 1 => 'aaa'),
);

var_dump(unique_matrix($matrix));
FabianoLothor
  • 2,752
  • 4
  • 25
  • 39
  • If 124 aaa and 124 baa, then it thinks that these are unique lines, but I wanted to make them non-unique and delete one of them, because they have similar Column 0 value. But I will accept this answer, because it's just a matter of small changes in the function. – Gusgus Jul 25 '12 at 19:43
  • this function is exactly what I needed.... (without the proposed changes in the previous comment) – gloomy.penguin Apr 11 '13 at 19:56
2

Try this:

$matrix = array(
    0 => array(0 => '123', 1 => 'aaa'),
    1 => array(0 => '124', 1 => 'aaa'),
    2 => array(0 => '124', 1 => 'aaa'),
    3 => array(0 => '124', 1 => 'aaa'),
    4 => array(0 => '114', 1 => 'aaa'),
    5 => array(0 => '124', 1 => 'aaa'),
    6 => array(0 => '124', 1 => 'aaa'),
    7 => array(0 => '124', 1 => 'aaa'),
    8 => array(0 => '124', 1 => 'aaa'),
    9 => array(0 => '124', 1 => 'baa'),
    10 => array(0 => '123', 1 => 'baa'),
    11 => array(0 => '1241', 1 => 'baa'),
);


$d = array();
foreach ($matrix AS $key => $value) {
    if (!array_search($value, $d)) {
        $d[] = $matrix[$key];
    }
}

var_dump($d);
Leidson Cruz
  • 89
  • 1
  • 6
2

If your array always returns the same value for column 1, when column 0 is repeated, you should use the flag SORT_REGULAR on array_unique, like this:

$matrix = array(
    array(0 => '123', 1 => 'aaa'),
    array(0 => '124', 1 => 'aaa'),
    array(0 => '124', 1 => 'aaa'),
);

var_dump(array_unique($matrix, SORT_REGULAR));
0

I have a couple of efficient techniques to share. (Demo)

If you don't care about the order of the results, this one-liner will preserve the first unique rows (based on the column value).

Code:

var_export(array_reverse(array_column(array_reverse($array), null, 0)));

This reverses the input and overwrites previously found rows with duplicate first column values -- because duplicates keys are not permitted in the same array level.

Or if you want to preserve the original order of rows, this will provide the same result without reversing.

Code:

$result = [];
foreach ($array as $row) {
    if (!isset($result[$row[0]])) {
        $result[$row[0]] = $row;
    }
}

var_export(array_values($result));

Using temporary keys and isset() is more efficient than array_search() because php is faster at searching for keys than values.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136