Eckonator
Eckonator

Reputation: 107

PHP - remove duplicate indexes from array, compared by one of it values

I have a PHP array with indexes, its values can be duplicated. I want to remove all duplicated indexes from this array:

array(3) {
  [0]=>
  array(5) {
    ["uid"]=>
    int(1)
    ["title"]=>
    string(26) "Title A"
    ["tstamp"]=>
    string(10) "1580296755"
  }
  [1]=>    // <----- should be removed, because it's tstamp is lower than it's duplicate
  array(5) {
    ["uid"]=>
    int(2)
    ["title"]=>
    string(33) "Title B"   // <----- duplicate value
    ["tstamp"]=>
    string(10) "1580296797"
  }
  [2]=>
  array(5) {
    ["uid"]=>
    int(3)
    ["title"]=>
    string(33) "Title B"   // <----- duplicate value
    ["tstamp"]=>
    string(10) "1580298366"
  }
}

So, Index 1 and 2 with the same title "Title B" are duplicated. Only the one with the higher tstamp should be exists, all older ones with same title should be removed from array:

array(3) {
  [0]=>
  array(5) {
    ["uid"]=>
    int(1)
    ["title"]=>
    string(26) "Title A"
    ["tstamp"]=>
    string(10) "1580296755"
  }
  [1]=>
  array(5) {
    ["uid"]=>
    int(3)
    ["title"]=>
    string(33) "Title B"
    ["tstamp"]=>
    string(10) "1580298366"
  }
}

Hope someone understand me and can help to solve my problem.

Upvotes: 0

Views: 1013

Answers (3)

Sherif
Sherif

Reputation: 11943

I don't believe you're actual concern here is the array keys, as your questions posits. I believe your real concern is in preventing duplicate values. If the array were sorted by the 'tstamp key this would be a simple column pluck operation.

So assuming ...

$arr = [
    ['uid' => 1, 'title' => 'Title A', 'tstamp' => 1580296755],
    ['uid' => 2, 'title' => 'Title B', 'tstamp' => 1580296797],
    ['uid' => 3, 'title' => 'Title B', 'tstamp' => 1580298366],
];

// Sorted ascendingly by 'tstamp' key
uasort($arr, function($a, $b) { return $a['tstamp'] <=> $b['tstamp']; });

// Pluck the title and overwriting is automatic
$result = array_column($arr, null, 'title');

var_dump($result);

The result would be:

array(2) {
  ["Title A"]=>
  array(3) {
    ["uid"]=>
    int(1)
    ["title"]=>
    string(7) "Title A"
    ["tstamp"]=>
    int(1580296755)
  }
  ["Title B"]=>
  array(3) {
    ["uid"]=>
    int(3)
    ["title"]=>
    string(7) "Title B"
    ["tstamp"]=>
    int(1580298366)
  }
}

Upvotes: 2

Aksen P
Aksen P

Reputation: 4599

You can use in_array function in such way:

$tmp = [];

foreach($ar as $ind=>$set){
    if(!in_array($set['title'],$tmp)){
        $tmp[] = $set['title'];
    } else {
        unset($ar[$ind]);
    } 
}

print_r($ar);

Demo

Output:

Array
(
    [0] => Array
        (
            [uid] => 1
            [title] => Title A
            [tstamp] => 1580296755
        )

    [1] => Array
        (
            [uid] => 2
            [title] => Title B
            [tstamp] => 1580296755
        )

    [3] => Array
        (
            [uid] => 4
            [title] => Title C
            [tstamp] => 1580296755
        )

)

or if you need to leave the last one appearance you can use next code:

$tmp = [];
$res = [];

foreach($ar as $ind=>$set){ 
    $tmp[$set['title']] = $ind; 
}

foreach($tmp as $title=>$ind){ 
    $res[] = $ar[$ind];
}

print_r($res);

Demo

Output:

Array
(
    [0] => Array
        (
            [uid] => 1
            [title] => Title A
            [tstamp] => 1580296755
        )

    [1] => Array
        (
            [uid] => 3
            [title] => Title B
            [tstamp] => 1580296755
        )

    [2] => Array
        (
            [uid] => 4
            [title] => Title C
            [tstamp] => 1580296755
        )

)

Upvotes: 0

GrumpyCrouton
GrumpyCrouton

Reputation: 8621

Just create an empty array, loop through your old array and add them to the new array with the key as the title.

<?php

$old = [
    ['uid' => 1, 'title' => 'Title A', 'tstamp' => 1580296755],
    ['uid' => 2, 'title' => 'Title B', 'tstamp' => 1580296797],
    ['uid' => 3, 'title' => 'Title B', 'tstamp' => 1580298366],
];

$new = [];
foreach($old as $row) {

    $title = $row['title'];

    //check if title exists as key of `$new` array.
    //if it does exist as a key, check if `tstamp` in the loop is higher than the existing record
    if(!array_key_exists($title, $new) || ($new[$title]['tstamp'] < $row['tstamp'])) {

        //update or insert record if the if-statement evaluates to true
        $new[$title] = $row;
    }
}

Output:

Array
(
    [Title A] => Array
        (
            [uid] => 1
            [title] => Title A
            [tstamp] => 1580296755
        )

    [Title B] => Array
        (
            [uid] => 3
            [title] => Title B
            [tstamp] => 1580298366
        )

)

This has the added benefit of being able to select titles easier, for example $new['Title A']. If you want the key indexes to still be numerical, you can use $new = array_values($new); to do so. If you use array_values(), the output matches your expected output exactly.

Upvotes: 1

Related Questions