xltmt
xltmt

Reputation: 61

PHP - Remove duplicate values in an array based on a key's value and empty values

I have the following output from a PHP array:

Array ( 
[0] => Array ( 
     [set1] => Array ( 
            [link] => xyz.com/def
            [time] => 2016-01-03
    [set2] => Array ( 
            [link] => 
            [time] => ) 
    [set3] => Array ( 
            [link] => 
            [time] => ) 
    ) 
[1] => Array ( 
    [set1] => Array ( 
            [link] => xyz.com/123
            [time] => 2016-01-03) 
    [set2] => Array ( 
            [link] => 
            [time] => ) 
    [set3] => Array ( 
            [link] => xyz.com/123
            [time] => 2016-01-03) 
    ) 
[2] => Array ( 
    [set1] => Array ( 
            [link] => xyz.com/abc
            [time] => 2015-12-03) 
    [set2] => Array (
            [link] => xyz.com/abc
            [time] => 2016-01-03) 
    [set3] => Array ( 
            [link] => xyz.com/123456
            [time] => 2016-01-03) 
    ) )

I would like to eliminate duplicate [link] regardless of the [time] - then I would like to eliminate the empty [link] values such as [0][set2], and finally have an output as follows:

[link] => xyz.com/def
[time] => 2016-01-03

[link] => xyz.com/123
[time] => 2016-01-03) 

[link] => xyz.com/abc
[time] => 2015-12-03

[link] => xyz.com/123456
[time] => 2016-01-03

This is what I tried:

$categoryUrlArray= array_unique(($categoryUrlArray, SORT_REGULAR);
    foreach ($categoryUrlArray as $categoryUrlLevel01) {
        $categoryUrlLevel01= array_unique($categoryUrlLevel01, SORT_REGULAR);
        foreach ($categoryUrlLevel01 as $categoryUrlLevel02) {
            echo $categoryUrlLevel02['link'];
            echo '<br/>';
            echo $categoryUrlLevel02['time'];
            echo '<br/><br/><br/>';
        }
    }

The problem with the above code is that duplicates are not being eliminated and empty values are still showing i.e. there are plenty of line breaks <br/> - that is why I know they are not being eliminated.

Upvotes: 0

Views: 322

Answers (3)

mickmackusa
mickmackusa

Reputation: 47904

Best practice for efficiently identifying unique values in your result array is accomplished by assigning temporary keys in the result array and checking !isset() for the identifying key (which is the link value). If you don't want to see these redundant/temporary keys in your output, call array_values().

*note, making iterated calls of in_array() is certainly more costly in terms of performance versus isset().

Code: (Demo)

$categoryUrlArray = [
    [
        "set1" => ["link" => "xyz.com/def", "time" => "2016-01-03"],
        "set2" => ["link" => "", "time" => ""],
        "set3" => ["link" => "", "time" => ""]
    ],
    [
        "set1" => ["link" => "xyz.com/123", "time" => "2016-01-03"],
        "set2" => ["link" => "", "time" => ""],
        "set3" => ["link" => "xyz.com/123", "time" => "2016-01-03"]
    ],
    [
        "set1" => ["link" => "xyz.com/abc", "time" => "2016-12-03"],
        "set2" => ["link" => "xyz.com/abc", "time" => "2016-01-03"],
        "set3" => ["link" => "xyz.com/123456", "time" => "2016-01-03"]
    ]
];

foreach ($categoryUrlArray as $groups) {
    foreach ($groups as $row) {
        if ($row["link"] && !isset($result[$row["link"]])) {  if "truthy" (not empty) and unique
            $result[$row["link"]] = $row;
        }
    }
}
var_export(array_values($result));

Output:

array (
  0 => 
  array (
    'link' => 'xyz.com/def',
    'time' => '2016-01-03',
  ),
  1 => 
  array (
    'link' => 'xyz.com/123',
    'time' => '2016-01-03',
  ),
  2 => 
  array (
    'link' => 'xyz.com/abc',
    'time' => '2016-12-03',
  ),
  3 => 
  array (
    'link' => 'xyz.com/123456',
    'time' => '2016-01-03',
  ),
)

Upvotes: 0

Samir Selia
Samir Selia

Reputation: 7065

Just add a condition to check if link is not blank !empty($categoryUrlLevel02['link'])

Below is the modified code:

($categoryUrlArray= array_unique(($categoryUrlArray, SORT_REGULAR);
foreach ($categoryUrlArray as $categoryUrlLevel01) {
    $categoryUrlLevel01= array_unique($categoryUrlLevel01, SORT_REGULAR);
    foreach ($categoryUrlLevel01 as $categoryUrlLevel02) {
        if(!empty($categoryUrlLevel02['link']))
        {
            echo $categoryUrlLevel02['link'];
            echo '<br/>';
            echo $categoryUrlLevel02['time'];
            echo '<br/><br/><br/>';
        }
    }
}

Upvotes: 0

roullie
roullie

Reputation: 2820

how about just checking inside the inner loop for blanks and duplicates? then save them all inside a new variable. like this

$newArr = array();
$links = array();
foreach($categoryUrlArray as $urls){
    foreach($urls as $url){
        if(!empty($url['link']) && !in_array($url['link'],$links)){
            $newArr[] = $url;
            $links[] = $url['link'];
        }
    }
}
var_dump($newArr);

will result to

array(4) {
  [0]=>
  array(2) {
    ["link"]=>
    string(11) "xyz.com/def"
    ["time"]=>
    string(10) "2016-01-03"
  }
  [1]=>
  array(2) {
    ["link"]=>
    string(11) "xyz.com/123"
    ["time"]=>
    string(10) "2016-01-03"
  }
  [2]=>
  array(2) {
    ["link"]=>
    string(11) "xyz.com/abc"
    ["time"]=>
    string(10) "2015-12-03"
  }
  [3]=>
  array(2) {
    ["link"]=>
    string(14) "xyz.com/123456"
    ["time"]=>
    string(10) "2016-01-03"
  }
}

Upvotes: 2

Related Questions