Asked  7 Months ago    Answers:  5   Viewed   52 times

How can I remove duplicate values from an array in PHP?

 Answers

30

Use array_unique().

Example:

$array = array(1, 2, 2, 3);
$array = array_unique($array); // Array is now (1, 2, 3)
Wednesday, March 31, 2021
 
pwaring
answered 7 Months ago
39

You can do:

function has_dupes($array) {
    $dupe_array = array();
    foreach ($array as $val) {
        if (++$dupe_array[$val] > 1) {
            return true;
        }
    }
    return false;
}
Wednesday, March 31, 2021
 
Keat
answered 7 Months ago
11

Function

function hierarchify(array $files) {
    /* prepare root node */
    $root = new stdClass;
    $root->children = array();
    /* file iteration */
    foreach ($files as $file) {
        /* argument validation */
        switch (true) {
            case !isset($file['name'], $file['virtual_path']):
            case !is_string($name = $file['name']):
            case !is_string($virtual_path = $file['virtual_path']):
                throw new InvalidArgumentException('invalid array structure detected.');
            case strpos($virtual_path, '/') === 0:
                throw new InvalidArgumentException('absolute path is not allowed.');
        }
        /* virtual url normalization */
        $parts = array();
        $segments = explode('/', preg_replace('@/++@', '/', $virtual_path));
        foreach ($segments as $segment) {
            if ($segment === '.') {
                continue;
            }
            if (null === $tail = array_pop($parts)) {
                $parts[] = $segment;
            } elseif ($segment === '..') {
                if ($tail === '..') {
                    $parts[] = $tail;
                }
                if ($tail === '..' or $tail === '') {
                    $parts[] = $segment;
                }
            } else {
                $parts[] = $tail;
                $parts[] = $segment;
            }
        }
        if ('' !== $tail = array_pop($parts)) {
            // skip empty
            $parts[] = $tail;
        }
        if (reset($parts) === '..') {
            // invalid upper traversal
            throw new InvalidArgumentException('invalid upper traversal detected.');
        }
        $currents = &$root->children;
        /* hierarchy iteration */
        foreach ($parts as $part) {
            while (true) {
                foreach ($currents as $current) {
                    if ($current->type === 'dir' and $current->name === $part) {
                        // directory already exists!
                        $currents = &$current->children;
                        break 2;
                    }
                }
                // create new directory...
                $currents[] = $new = new stdClass;
                $new->type = 'dir';
                $new->name = $part;
                $new->children = array();
                $currents = &$new->children;
                break;
            }
        }
        // create new file...
        $currents[] = $new = new stdClass;
        $new->type = 'file';
        $new->name = $name;
    }
    /* convert into array completely */
    return json_decode(json_encode($root->children), true);
}

Example

Case 1:

$files = array(
    0 => array (
        'name' => 'b.txt',
        'virtual_path' => 'A/B//',
    ),
    1 => array(
        'name' => 'a.txt',
        'virtual_path' => '././A/B/C/../..',
    ),
    2 => array(
        'name' => 'c.txt',
        'virtual_path' => './A/../A/B/C//////',
    ),
    3 => array(
        'name' => 'root.txt',
        'virtual_path' => '',
    ),
);
var_dump(hierarchify($files));

will output...

array(2) {
  [0]=>
  array(3) {
    ["type"]=>
    string(3) "dir"
    ["name"]=>
    string(1) "A"
    ["children"]=>
    array(2) {
      [0]=>
      array(3) {
        ["type"]=>
        string(3) "dir"
        ["name"]=>
        string(1) "B"
        ["children"]=>
        array(2) {
          [0]=>
          array(2) {
            ["type"]=>
            string(4) "file"
            ["name"]=>
            string(5) "b.txt"
          }
          [1]=>
          array(3) {
            ["type"]=>
            string(3) "dir"
            ["name"]=>
            string(1) "C"
            ["children"]=>
            array(1) {
              [0]=>
              array(2) {
                ["type"]=>
                string(4) "file"
                ["name"]=>
                string(5) "c.txt"
              }
            }
          }
        }
      }
      [1]=>
      array(2) {
        ["type"]=>
        string(4) "file"
        ["name"]=>
        string(5) "a.txt"
      }
    }
  }
  [1]=>
  array(2) {
    ["type"]=>
    string(4) "file"
    ["name"]=>
    string(8) "root.txt"
  }
}

Case 2:

$files = array(
    0 => array (
        'name' => 'invalid.txt',
        'virtual_path' => '/A/B/C',
    ),
);
var_dump(hierarchify($files));

will throw...

Fatal error: Uncaught exception 'InvalidArgumentException' with message 'absolute path is not allowed.'

Case 3:

$files = array(
    0 => array (
        'name' => 'invalid.txt',
        'virtual_path' => 'A/B/C/../../../../../../../..',
    ),
);
var_dump(hierarchify($files));

will throw...

Fatal error: Uncaught exception 'InvalidArgumentException' with message 'invalid upper traversal detected.'
Wednesday, March 31, 2021
 
davidb
answered 7 Months ago
73

Bit late, but may help someone looking for same answer. I used this very simple approach to;

  1. remove all the keys from nested arrays that contain no value, then
  2. remove all the empty nested arrays.

$postArr = array_map('array_filter', $postArr);
$postArr = array_filter( $postArr );
Friday, July 23, 2021
 
subroutines
answered 3 Months ago
14

A quick way using array_reduce would look like:

$unique = array_reduce($subject, function($final, $article){
    static $seen = array();
    if ( ! array_key_exists($article['fk_article_id'], $seen)) {
        $seen[$article['fk_article_id']] = NULL;
        $final[] = $article;
    }
    return $final;
});

Try a working example.


Edit: Seems you don't want to work with the aggregated results. Here are two other thoughts:

Filtering in PHP

$seen = array();
while ($row = pg_fetch_assoc($authors_result)) {
    // Skip this row if we have already seen its article id
    if (array_key_exists($row['fk_article_id'], $seen)) {
        continue;
    }
    // Note that we have seen this article
    $seen[$row['fk_article_id']] = NULL;
    // Do whatever with your row
    var_dump($row);
}

Filtering in the DB

The idea here is to change the query being executed so that the repeated article ids do not appear in the result set. How this is done will depend on the query that you're already using.

Friday, August 6, 2021
 
octern
answered 3 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share