Filter/Remove Rows Where Column Value Is Found More Than Once in a Multidimensional Array

Filter/Remove rows where column value is found more than once in a multidimensional array

For a clearer "minimal, complete, verifiable example", I'll use the following input array in my demos:

$array = [
['user_id' => 82, 'ac_type' => 1],
['user_id' => 80, 'ac_type' => 5],
['user_id' => 76, 'ac_type' => 1],
['user_id' => 82, 'ac_type' => 2],
['user_id' => 80, 'ac_type' => 5]
];
// elements [0] and [3] have the same user_id, but different ac_type
// elements [1] and [4] have identical row data
  1. Unconditionally push rows into a result array and assign associative first-level keys, then re-index with array_values(). This approach overwrites earlier duplicate rows with later occurring ones.

    array_column demo:

    var_export(array_values(array_column($array, null, 'user_id')));

    foreach demo:

    $result = [];
    foreach ($array as $row) {
    $result[$row['user_id']] = $row;
    }
    var_export(array_values($result));

    Output:

    [
    ['user_id' => 82, 'ac_type' => 2], // was input row [3]
    ['user_id' => 80, 'ac_type' => 5], // was input row [4]
    ['user_id' => 76, 'ac_type' => 1] // was input row [2]
    ]
  2. Use a condition or the null coalescing assignment operator to preserve the first occurring row while removing duplicates.

    foreach null coalescing assignment demo:

    foreach ($array as $a) {
    $result[$a['user_id']] ??= $a; // only store if first occurrence of user_id
    }
    var_export(array_values($result)); // re-index and print

    foreach isset demo:

    foreach ($array as $a) {
    if (!isset($result[$a['user_id']])) {
    $result[$a['user_id']] = $a; // only store if first occurrence of user_id
    }
    }
    var_export(array_values($result)); // re-index and print

    Output:

    [
    ['user_id' => 82, 'ac_type' => 1], // was input row [0]
    ['user_id' => 80, 'ac_type' => 5], // was input row [1]
    ['user_id' => 76, 'ac_type' => 1] // was input row [2]
    ]
  3. It is also possible to unconditionally push data AND avoid a condition, but the row order may differ between the input and output (if it matters to you).

    array_reverse, array_column demo:

    var_export(array_values(array_column(array_reverse($array), null, 'user_id')));

    array_reduce demo:

    var_export(
    array_values(
    array_reduce(
    $array,
    fn($res, $row) => array_replace([$row['user_id'] => $row], $res),
    []
    )
    )
    );

    foreach array_reverse demo:

    $result = [];
    foreach (array_reverse($array) as $row) {
    $result[$row['user_id']] = $row;
    }
    var_export(array_values($result));

    Output:

    [
    ['user_id' => 80, 'ac_type' => 5], // was input row [1]
    ['user_id' => 82, 'ac_type' => 1], // was input row [0]
    ['user_id' => 76, 'ac_type' => 1] // was input row [2]
    ]

A warning about a fringe case not expressed in this example: if you are using row values as identifiers that may be corrupted upon being used as keys, the above techniques will give unreliable results. For instance, PHP does not allow float values as keys (they will cause an error or be truncated, depending on your PHP version). Only in these fringe cases might you consider using inefficient, iterated calls of in_array() to evaluate uniqueness.


Using array_unique(..., SORT_REGULAR) is only suitable when determining uniqueness by ENTIRE rows of data.

array_unique demo:

var_export(array_unique($array, SORT_REGULAR));

Output:

[
['user_id' => 82, 'ac_type' => 1], // was input row [0]
['user_id' => 80, 'ac_type' => 5], // was input row [1]
['user_id' => 76, 'ac_type' => 1] // was input row [2]
['user_id' => 82, 'ac_type' => 2], // was input row [3]
]

How to remove duplicates value of same key of multidimensional array in PHP

If you need only latest entry for each unique status, you can simply use status's value as a key in another associative array and keep overriding it at every iteration in the loop. In the end, you will only be left with unique results with latest entries.

Say, you have this array in a variable called $data, then you could loop like below:

<?php

$set = [];

foreach($data as $o){
$set[ $o->status ] = $o;
}

$set = array_values($set);// if you don't like status keys

print_r($set);

Remove all duplicate data from a multi-dimensional array

So the issue here is that the array_unique solutions expect the entire value to be equivalent - they don't just compare based on your ID field.

Instead, you probably want to loop through the array and keep track of which IDs you've seen, and only take those elements for which you haven't seen the ID before.

function filter_duplicate_id_cards($data) {
$seen = array(); // To keep track of the IDs we've seen
$filtered = array(); // Will hold the result

foreach($data as $item) {
if(array_key_exists($item['id_card'], $seen)) {
// We already encountered this id card before.
continue;
}

// Never-before seen id card, append it to the result and set the key in $seen
$filtered[] = $item;
$seen[$item['id_card']] = TRUE;
}

return $filtered;
}

Note that this uses the map form of a PHP array, rather than just appending seen IDs to the list form and using something like in_array to check if we've seen the key. That's important for performance reasons, especially if we're going to be working on large datasets - in_array is O(n) with the # of items in the array whereas array_key_exists is O(1).

A more generic version of this function would look like this:

function filter_duplicate_field($data, $field) {
$seen = array(); // To keep track of the keys we've seen
$filtered = array(); // Will hold the result

foreach($data as $item) {
if(array_key_exists($item[$field], $seen)) {
// We already encountered this key before.
continue;
}

// Never-before seen key, append it to the result and set the key in $seen
$filtered[] = $item;
$seen[$item[$field]] = TRUE;
}

return $filtered;
}

You could then call it like $result = filter_duplicate_field($data, 'id_card');.

Filter array of associative rows to retain only rows with unique value in specified column

Simple solution using regular foreach loop:

$rows = [
['id' => 1, 'code' => '342'],
['id' => 2, 'code' => '765'],
['id' => 3, 'code' => '134'],
['id' => 1, 'code' => '342']
];

$ids = [];
foreach ($rows as $k => $item) {
if (in_array($item['id'], $ids)){
unset($rows[$k]);
} else {
$ids[] = $item['id'];
}
}

print_r($rows);

PHP - Elegant way of removing values from Associative Arrays based on a key value duplication

return array_intersect_key($results, array_unique(array_column($results, 'nid')));

How to remove duplicate entries from multidimensional array?

Serialization is used to compare if the entire arrays are indentical, not just one key.

You can extract the array and index (which must be unique) by linked_article_id:

$input = array_column($input, null, 'linked_article_id');

If you really need to re-index after (optional):

$input = array_values(array_column($input, null, 'linked_article_id'));

I don't see how anyone could be running PHP < 5.5.0 now, but just in case:

foreach($input as $v) {
$result[$v['linked_article_id']] = $v;
}

Then if needed:

$result = array_values($result);

PHP - array_map 2 columns and remove duplicate rows by key

If you want the first occurrence use @TheFirstBird answer. If you want the last occurrence you can do it simpler buy using array_column and array_values as:

$newArr = array_values(array_column($purchases, null, "product_id")); 

Notice the second argument of array_column is null meaning take the entire element.

Live example: 3v4l

References: array-column, array-values

Removing duplicate array values by e-mail

A simple way if you are using a loop to add the details in ( which is what I am assuming your current code is doing) is to index the $guestOutput by the e-mail address. So as you add in new details, you will just overwrite the previous details...

$guestOutput[$guest->guestEmail] = [
'firstName' => $guest->guestFirstName,
'lastName' => $guest->guestLastName,
'email' => $guest->guestEmail,
];

If you don't need the index at the end of the loop, you can use:

$guestOutput = array_values($guestOutput);


Related Topics



Leave a reply



Submit