94

I have a 2d array and need to isolate the unique columns from one column.

$array = [
    [..., 'key' => 1, ...],
    [..., 'key' => 2, ...],
    [..., 'key' => 3, ...],
    [..., 'key' => 1, ...],
    [..., 'key' => 2, ...],
    [..., 'key' => 3, ...],
    [..., 'key' => 4, ...],
    [..., 'key' => 5, ...],
    [..., 'key' => 6, ...]
];

How do I add elements to the result array only if they aren't in there already? I have the following:

$a = [];
// organize the array
foreach ($array as $k => $v) {
    foreach ($v as $key => $value) {
        if ($key == 'key') {
            $a[] = $value;
        }
    }
}
print_r($a);

Output:

Array
(
  [0] => 1
  [1] => 2
  [2] => 3
  [3] => 1
  [4] => 2
  [5] => 3
  [6] => 4
  [7] => 5
  [8] => 6
)

Instead, I want $a to consist of the unique values. (I know I can use array_unique() after looping to get the desired results, but I just want to know of any other ways.)

1
  • For those searching for Laravel solution, the Arr::wrap() is the answer, see docs. Commented Jul 9, 2022 at 7:00

16 Answers 16

190

You should use the PHP function in_array (see http://php.net/manual/en/function.in-array.php).

if (!in_array($value, $array))
{
    $array[] = $value; 
}

This is what the documentation says about in_array:

Returns TRUE if needle is found in the array, FALSE otherwise.

Sign up to request clarification or add additional context in comments.

1 Comment

Making iterated value-based checks is likely to be the least performant process.
70

You'd have to check each value against in_array:

$a=array();
// organize the array by cusip
foreach($array as $k=>$v){
    foreach($v as $key=>$value){
        if(!in_array($value, $a)){
        $a[]=$value;
        }
    }
}

1 Comment

As the volume of the input data increases, in_array() will experience increasingly worse performance.
30

Since you seem to only have scalar values an PHP’s array is rather a hash map, you could use the value as key to avoid duplicates and associate the $k keys to them to be able to get the original values:

$keys = array();
foreach ($array as $k => $v){
    if (isset($v['key'])) {
        $keys[$value] = $k;
    }
}

Then you just need to iterate it to get the original values:

$unique = array();
foreach ($keys as $key) {
    $unique[] = $array[$key]['key'];
}

This is probably not the most obvious and most comprehensive approach but it is very efficient as it is in O(n).

Using in_array instead like others suggested is probably more intuitive. But you would end up with an algorithm in O(n2) (in_array is in O(n)) that is not applicable. Even pushing all values in the array and using array_unique on it would be better than in_array (array_unique sorts the values in O(n·log n) and then removes successive duplicates).

2 Comments

There's a suggested edit by @xmedeko that suggests that the cost is O(n logn) not O(n) because of "the cost on PHP hashing", could both of you reach an agreement here? :-)
IMHO array_unique preserves the original order values, while your solutions doesn't.
17
if (!in_array(...))  
  array_push(..)

Comments

11

Easy to write, but not the most effective one:

$array = array_unique(array_merge($array, $array_to_append));

This one is probably faster:

$array = array_merge($array, array_diff($array_to_append, $array));

1 Comment

According to my IDE (PHPStorm, since I have not done performance comparison) the first one is faster. PHPStorm gave me a "resource intensive operation used in loop" warning when using array_merge + array_diff.
6
if (!in_array($value, $a))
  $a[]=$value;

Comments

4

Try adding as key instead of value:

Adding an entry

function addEntry($entry) {
    $this->entries[$entry] = true;
}

Getting all entries

function getEntries() {
    return array_keys($this->enties);
}

1 Comment

This is how Java implements HashSets (with an embedded HashMap and a value, I think consisting of a static new Object())
4

If you're okay with using shorthands in your code (instead of writing explicit if blocks, like some coding standards recommend), you can further simplify Marius Schulz's answer with this one-liner:

in_array ($value, $array) || $array [] = $value;

Comments

3

If you don't care about the ordering of the keys, you could do the following:

$array = YOUR_ARRAY
$unique = array();
foreach ($array as $a) {
    $unique[$a] = $a;
}

Comments

3

Since there are a ton of ways to accomplish the desired results and so many people provided !in_array() as an answer, and the OP already mentions the use of array_unique, I would like to provide a couple alternatives.

Using array_diff (php >= 4.0.1 || 5) you can filter out only the new array values that don't exist. Alternatively you can also compare the keys and values with array_diff_assoc. http://php.net/manual/en/function.array-diff.php

$currentValues = array(1, 2);
$newValues = array(1, 3, 1, 4, 2);
var_dump(array_diff($newValues, $currentValues));

Result:

Array
(
    [1] => 3
    [3] => 4
)

http://ideone.com/SWO3D1

Another method is using array_flip to assign the values as keys and compare them using isset, which will perform much faster than in_array with large datasets. Again this filters out just the new values that do not already exist in the current values.

$currentValues = [1, 2];
$newValues = [1, 3, 1, 4, 2];
$a = array();
$checkValues = array_flip($currentValues);
foreach ($newValues as $v) {
    if (!isset($checkValues[$v])) {
        $a[] = $v;
    }
}

Result:

Array
(
    [0] => 3
    [1] => 4
)

http://ideone.com/cyRyzN

With either method you can then use array_merge to append the unique new values to your current values.

  1. http://ideone.com/JCakmR
  2. http://ideone.com/bwTz2u

Result:

Array
(
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => 4
)

Comments

1

you can try using "in_array":

function insert_value($value, &$_arr) {
    if (!in_array($value, $_arr)) {
        $_arr[] = $value;
    }
}

Comments

0

Taking Gumbo's idea, making the code work:

$array = array('111111','222222','3333333','4444','5555', 
'AAAAAA', 'BBBBBB', 'CCC', 'DDDDDDD', 'EEEEEEEE', 'FFFFFF', 'GGG',
'AAAAAA', 'BBBBBB', 'CCC', 'DDDDDDD', 'EEEEEEEE', 'FFFFFF', 'GGG',
'222222', 
'666666', '777777', 'HHHH');

print_r($array);

$keys= array();
foreach ($array as $k => $v){
    if (isset($v['value'])) {
        $keys[$v] = $k;
    }
}
$unique = array();
foreach ($keys as $key) {
    $unique[] = $array[$key];
}
print "<br><br>";
print_r($unique);

Gives this:

Array
(
    [0] => 111111
    [1] => 222222
    [2] => 3333333
    [3] => 4444
    [4] => 5555
    [5] => AAAAAA
    [6] => BBBBBB
    [7] => CCC
    [8] => DDDDDDD
    [9] => EEEEEEEE
    [10] => FFFFFF
    [11] => GGG
    [12] => AAAAAA
    [13] => BBBBBB
    [14] => CCC
    [15] => DDDDDDD
    [16] => EEEEEEEE
    [17] => FFFFFF
    [18] => GGG
    [19] => 222222
    [20] => 666666
    [21] => 777777
    [22] => HHHH
)

Array
(
    [0] => 111111
    [1] => 222222
    [2] => 3333333
    [3] => 4444
    [4] => 5555
    [5] => AAAAAA
    [6] => BBBBBB
    [7] => CCC
    [8] => DDDDDDD
    [9] => EEEEEEEE
    [10] => FFFFFF
    [11] => GGG
    [12] => 666666
    [13] => 777777
    [14] => HHHH
)

Comments

0

With array_flip() it could look like this:

$flipped = array_flip($opts);
$flipped[$newValue] = 1;
$opts = array_keys($flipped);

With array_unique() - like this:

$opts[] = $newValue;
$opts = array_values(array_unique($opts));

Notice that array_values(...) — you need it if you're exporting array to JavaScript in JSON form. array_unique() alone would simply unset duplicate keys, without rebuilding the remaining elements'. So, after converting to JSON this would produce object, instead of array.

>>> json_encode(array_unique(['a','b','b','c']))
=> "{"0":"a","1":"b","3":"c"}"

>>> json_encode(array_values(array_unique(['a','b','b','c'])))
=> "["a","b","c"]"

Comments

0

To populate a flat, indexed array of unique values from a single column of scalar values from a 2d array, you can use array_column() and nominate the 2nd and 3rd parameters as the same desired column.

Because PHP doesn't allow keys on the same level of an array to be duplicated, you get the desired unique value results.

This technique is reliable because none of the values being isolated will be mutated by PHP upon being used as keys -- this is not true of nulls, floats, booleans, and more data types.

array_values() is only necessary if you want to re-index the keys; otherwise you can leave the temporary keys and avoid the extra function call.

Code: (Demo)

var_export(
    array_values(
        array_column($array, 'key', 'key')
    )
);

Output:

array (
  0 => 1,
  1 => 2,
  2 => 3,
  3 => 4,
  4 => 5,
  5 => 6,
)

For the implementation of a language construct for iteration, you can use a body-less foreach() and access the key column value twice to push associative values into the result array. Demo

$result = [];
foreach ($array as ['key' => $k, 'key' => $result[$k]]);
var_export(array_values($result));

Topical reading: While destructuring an array, can the same element value be accessed more than once?

Comments

-1

You can also use +=

$options1 = []

$options1 += [
      'id' => NULL
    ];

will result in $options1 equal to:

[
  'id' => NULL
];

where as

$options2 = ['id' => '121sdd23']

$options2 += [
      'id' => NULL
    ];

will result in $options2 equal to:

[
  'id' => '121sdd23'
];

Comments

-4

Try this code, I got it from here

$input = Array(1,2,3,1,2,3,4,5,6);
$input = array_map("unserialize", array_unique(array_map("serialize", $input)));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.