How can you get unique values from multiple arrays using array_unique? - php

Is there any way to put two or more arrays into the array_unique() function?
If not, is there any other solution to get unique results from multiple arrays?

The answer to the first part of your question is NO.
The array_unique function definition in the PHP manual states that array_unique takes exactly two arguments, one array, and an optional integer that determines the sorting behavior of the function.
array array_unique ( array $array [, int $sort_flags = SORT_STRING ] )
Rather than take the manual's word for it, here are some test arrays.
$one_array = ['thing', 'another_thing', 'same_thing', 'same_thing'];
$two_arrays = ['A', 'B', 'C', 'thing', 'same_thing'];
$or_more_arrays = ['same_thing', 1, 2, 3];
A couple of test show that the function does work as advertised:
$try_it = array_unique($one_array);
returns ['thing', 'another_thing', 'same_thing'];
$try_it = array_unique($one_array, $two_arrays);
gives you a warning
Warning: array_unique() expects parameter 2 to be integer, array given
and returns null.
$try_it = array_unique($one_array, $two_arrays, $or_more_arrays);
also gives you a warning
Warning: array_unique() expects at most 2 parameters, 3 given
and returns null.
The answer to the second part of your question is YES.
To get unique values using array_unique, you do have to have one array of values. You can do this, as u_mulder commented, by using array_merge to combine the various input arrays into one before using array_unique.
$unique = array_unique(array_merge($one_array, $two_arrays, $or_more_arrays));
returns
['thing', 'another_thing', 'same_thing', 'A', 'B', 'C', 1, 2, 3];
If instead of several individual array variables, you have an array of arrays like this:
$multi_array_example = [
[1, 2, 3],
[2, 3, 4],
[3, 4, 5],
[4, 5, 6]
];
Then you can unpack the outer array into array merge to flatten it before using array_unique.
$unique = array_unique(array_merge(...$multi_array_example));
Or in older PHP versions (<5.6) before argument unpacking, you can use array_reduce with array_merge.
$unique = array_unique(array_reduce($multi_array_example, 'array_merge', []));
returns [1, 2, 3, 4, 5, 6]

By default, array_unique() takes two parameters, the array, of type array takes the input array and the second parameter, sorting of type int takes the sorting behavior. You can read more on it in the PHP manual for array_unique().
But as suggested by #u_mulder, you merge the array first, probably into a temporary array (you can learn how to do that here) and then apply the array_unique to that temporary array.

Related

PHP - Sort multi-dimensional array of number arrays

I have an array:
$arr = [
[4,6],
[1,2,3],
[7,8,9]
];
I'd like to sort it so the result is
$arr = [
[1,2,3],
[4,6],
[7,8,9]
];
If I apply sort($arr), it first sorts by array length and then compares the values. So I get
$arr = [
[4,6],
[7,8,9],
[1,2,3],
];
which is wrong for my purposes.
I could use a sorting algorithm to compare the elements.
Or I could create another array with each element imploded and then sort it.
But was wondering if there was an inbuilt or quicker way of getting this?
Thanks
You can use rsort() to get the order you are expecting.

How do I get the end element of an array

I have an array (as shown below). It has a and b, the numbers inside of each of them. However, when I use the end() function, it gives me b's array. I want the actual b letter. to be printed, not the number array. How can I do this?
<?php
$array = array("a" => array(1, 2, 3),
"b" => array(4, 5, 6));
$end = end($array);
print_r($end); // gives me 4, 5, 6. I want the value b
Use end with array_keys instead:
$array = array("a" => array(1, 2, 3),
"b" => array(4, 5, 6));
$keys = array_keys($array);
$end = end($keys);
print_r($end);
Note that since end adjusts the array pointer (hence you can't pass the output from array_keys directly to end without a notice level error), it's probably preferable to simply use
echo $keys[count($keys)-1];
Simply
$array = array("a" => array(1, 2, 3),"b" => array(4, 5, 6));
end($array);
echo key($array);
Output
b
Sandbox
the call to end puts the internal array pointer at the end of the array, then key gets the key of the current position (which is now the last item in the array).
To reset the array pointer just use:
reset($array); //moves pointer to the start
You cant do it in one line, because end returns the array element at the end and key needs the array as it's argument. It's a bit "Weird" because end moves the internal array pointer, which you don't really see.
Update
One way I just thought of that is one line, is to use array reverse and key:
echo key(array_reverse($array));
Basically when you do array_reverse it flips the order around and returns the reversed array. We can then use this array as the argument for key(), which gets the (current) first key of our now backwards array, or the last key of the original array(sort of a double negative).
Output
b
Sandbox
Enjoy!
A simple way to do it would be to loop through the keys of the array and store the key at each index.
<?php
$array = array("a" => array(1, 2, 3),
"b" => array(4, 5, 6));
foreach ($array as $key => $value) $end = $key;
// This will overwrite the value until you get to the last index then print it out
print_r($end);

array_filter based on keys from another array

I have two arrays:
$arr1 = array('a' => 10, 'b' => 20);
$arr2 = array('a' => 10, 'b' => 20, 'c' => 30);
How can I use array_filter to drop elements from $arr2 that don't exist in $arr1 ? Like "c" in my example...
There is a function specifically made for this purpose: array_intersect():
array_intersect — Computes the intersection of arrays
$arr2 = array_intersect($arr1, $arr2);
If you want to compare keys, not the values like array_intersect(), use array_intersect_key():
array_intersect_key — Computes the intersection of arrays using keys for comparison
$arr2 = array_intersect_key($arr1, $arr2);
If you want to compare key=>value pairs, use array_intersect_assoc():
array_intersect_assoc — Computes the intersection of arrays with additional index check
$arr2 = array_intersect_assoc($arr1, $arr2);
Use in_array in your array_filter callback:
$arr2 = array_filter($arr2, function($e) use ($arr1) {
return in_array($e, $arr1);
});
Note that this will regard the values of the elements, not the keys. array_filter will not give you any key to work with so if that is what you need a regular foreach loop may be better suited.
To get the elements that exist in $arr2 which also exist in $arr1 (i.e. drop elements of $arr2 that don't exist in $arr1), you can intersect based on the key like this:
array_intersect_key($arr2, $arr1); // [a] => 10, [b] => 20
Update
Since PHP 7 it's possible to pass mode to array_filter() to indicate what value should be passed in the provided callback function:
array_filter($arr2, function($key) use ($arr1) {
return isset($arr1[$key]);
}, ARRAY_FILTER_USE_KEY);
Since PHP 7.4 you can also drop the use () syntax by using arrow functions:
array_filter($arr2, fn($key) => isset($arr1[$key]), ARRAY_FILTER_USE_KEY);

Somewhat efficient way to append array 1 to array 2, while preserving the numeric keys of array 2, and adding keys n through n + x to array 1?

This is sort of two questions, but there may be one overall answer for the whole problem. I have an array that I need to append onto another array. Both arrays must have specific numeric keys. My problems are:
I need the numeric keys for the array that I am appending onto to be preserved.
array_splice() and array_merge() won't work to join the arrays because numeric keys in both arrays will be reset.
I need to make the keys of the newly added elements to be n through n + x, meaning if n is 100 and x is 25, the keys for the newly added elements should be 100 through 125.
Can anyone think of a somewhat efficient way of doing this?
EDIT
For anyone curious, found a better way of adding the correct keys to the array.
// add correct keys
$array_segment = array_combine(range($offset, $offset + count($array_segment) - 1), $array_segment);
// merge arrays while maintaining keys
$first_array = $first_array + $array_segment;
I think this is a very simple solution but, if I understand well what you want, it works and it's fast. In my opinion you can use this approach:
$array1 = array(1 => 'a', 2 => 'b', 3 => 'c');
$array2 = array(4 => 'd', 5 => 'e', 6 => 'f');
foreach($array2 as $key => $value)
$array1[$key] = $value;
var_dump($array1);
$array1[] = 'g';
$array1[] = 'h';
var_dump($array1);
You can see the result here:
http://codepad.org/ogD9drpK
Another way which will avoid the foreach is to execute this instruction:
// avoid the loop
//foreach($array2 as $key => $value)
// $array1[$key] = $value;
$array1 += $array2;
You can see the result here:
http://codepad.org/cZxCfRn6

PHP Built-in Method to Get Array Values Given a List of Keys

I have an 'dictionary' array such as this:
$arr['a']=5;
$arr['b']=9;
$arr['as']=56;
$arr['gbsdfg']=89;
And I need a method that, given a list of the array keys, I can retrieve the corresponding array values. In other words, I am looking for a built-in function for the following methods:
function GetArrayValues($arrDictionary, $arrKeys)
{
$arrValues=array();
foreach($arrKeys as $key=>$value)
{
$arrValues[]=$arrDictionary[$key]
}
return $arrValues;
}
I am so sick of writing this kind of tedious transformation that I have to find a built-in method to do this. Any ideas?
array_intersect_key
If you have an array of keys as values you can use array_intersect_key combined with array_flip. For example:
$values = ['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4];
$keys = ['a', 'c'];
array_intersect_key($values, array_flip($keys));
// ['a' => 1, 'c' => 3]

Categories