You want array_keys with the search value
array_keys($list[0], "2009-09-09");
which will return an array of the keys with the specified value, in your case [0, 2]. If you want to find the duplicates as well, you can first make a pass with array_unique, then iterate over that array using array_keys on the original; anything which returns an array of length > 1 is a duplicate, and the result is the keys in which the duplicates are stored. Something like...
$uniqueKeys = array_unique($list[0])
foreach ($uniqueKeys as $uniqueKey)
{
$v = array_keys($list[0], $uniqueKey);
if (count($v) > 1)
{
foreach (
key)
{
// Work with $list[0][$key]
}
}
}
Answer from Adam Wright on Stack OverflowYou want array_keys with the search value
array_keys($list[0], "2009-09-09");
which will return an array of the keys with the specified value, in your case [0, 2]. If you want to find the duplicates as well, you can first make a pass with array_unique, then iterate over that array using array_keys on the original; anything which returns an array of length > 1 is a duplicate, and the result is the keys in which the duplicates are stored. Something like...
$uniqueKeys = array_unique($list[0])
foreach ($uniqueKeys as $uniqueKey)
{
$v = array_keys($list[0], $uniqueKey);
if (count($v) > 1)
{
foreach (
key)
{
// Work with $list[0][$key]
}
}
}
In array_search() we can read:
If needle is found in haystack more than once, the first matching key is returned. To return the keys for all matching values, use
array_keys()with the optionalsearch_valueparameter instead.
In array_search manual there's a mention:
To return the keys for all matching values, use
array_keys()with the optionalsearch_valueparameter instead.
So, instead of
$key = array_search($needle, array_column($haystack, $column));
use
$keys = array_keys(array_column($haystack, $column), $needle); // notice order of arguments
Boring solution using a foreach loop:
function get_in_array( string $needle, array $haystack, string $column){
$matches = [];
foreach( $haystack as $item ) if( $item[ $column ] === $needle ) $matches[] = $item;
return $matches;
}
Using array_filter:
function get_in_array( string $needle, array $haystack, string $column ){
return array_filter( $haystack, function( $item )use( $needle, $column ){
return $item[ $column ] === $needle;
});
}
If you want to verify that either value is in the $array_under_test, array_intersect may not be the best option. It will continue to test for collisions even after it finds a match.
For two search strings you can just do:
if (in_array('a', $array_under_test) || in_array('b', $array_under_test)) {
// Success!
}
This will stop searching if 'a' is found in the $array_under_test.
For more than two values, you can use a loop:
foreach ($match_array as $value) {
if (in_array($value, $array_under_test)) {
// Success!
break;
}
}
In addition to p.w.s.g's answer (which seems fine):
If you have lots of values you need to find, you can use a hash:
// the values go into keys of the array
$needles = array('value1' => 1, 'value2' => 1, 'value3' => 1);
$haystack = array('test', 'value1', 'etc');
// only go through the array once
$found = false;
foreach($haystack as $data) {
if (isset($needles[$data])) {
$found = true; break;
}
}
It's worth doing this if you search $haystack a lot of times.
Intersect the targets with the haystack and make sure the intersection count is equal to the target's count:
Copy$haystack = array(...);
$target = array('foo', 'bar');
if(count(array_intersect($haystack, $target)) == count($target)){
// all of $target is in $haystack
}
Note that you only need to verify the size of the resulting intersection is the same size as the array of target values to say that $haystack is a superset of $target.
To verify that at least one value in $target is also in $haystack, you can do this check:
Copy if(count(array_intersect($haystack, $target)) > 0){
// at least one of $target is in $haystack
}
Searching the array for multiple values corresponds to the set operations (set difference and intersection), as you will see below.
I also provide usage examples that clearly demonstrate both options.
ALL needles exist
Copyfunction in_array_all(array $needles, array $haystack): bool {
return array_diff($needles, $haystack) === [];
}
$animals = ["bear", "tiger", "zebra"];
in_array_all(["bear", "zebra"], $animals); // true, both are animals
in_array_all(["bear", "toaster"], $animals); // false, toaster is not an animal
ANY of the needles exist
Copyfunction in_array_any(array $needles, array $haystack): bool {
return array_intersect($needles, $haystack) !== [];
}
$animals = ["bear", "tiger", "zebra"];
in_array_any(["toaster", "tiger"], $animals); // true, tiger is an amimal
in_array_any(["toaster", "brush"], $animals); // false, no animals here
Important consideration
If the set of needles you are searching for is small and known upfront, your code might be clearer if you just use the logical chaining of in_array calls, for example:
Copy$animals = getAllAnimals();
$all = in_array("tiger", $animals) && in_array("toaster", $animals) && ...
$any = in_array("bear", $animals) || in_array("zebra", $animals) || ...
function searchForId($id, $array) {
foreach ($array as $key => $val) {
if ($val['uid'] === $id) {
return $key;
}
}
return null;
}
This will work. You should call it like this:
$id = searchForId('100', $userdb);
It is important to know that if you are using === operator compared types have to be exactly same, in this example you have to search string or just use == instead ===.
Based on angoru answer. In later versions of PHP (>= 5.5.0) you can use one-liner.
$key = array_search('100', array_column($userdb, 'uid'));
Here is documentation: http://php.net/manual/en/function.array-column.php.
If you are using (PHP 5 >= 5.5.0) you don't have to write your own function to do this, just write this line and it's done.
If you want just one result:
$key = array_search(40489, array_column($userdb, 'uid'));
For multiple results
$keys = array_keys(array_column($userdb, 'uid'), 40489);
In case you have an associative array as pointed in the comments you could make it with:
single result :
$key = array_search(40489, array_combine(array_keys($userdb), array_column($userdb, 'uid')))
Multiple results :
$keys = array_keys(array_combine(array_keys($userdb), array_column($userdb, 'uid')),40489);
If you are using PHP < 5.5.0, you can use this backport, thanks ramsey!
Update: I've been making some simple benchmarks and the multiple results form seems to be the fastest one, even faster than the Jakub custom function!
Perhaps this will be useful:
/**
* Multi-array search
*
* @param array $array
* @param array $search
* @return array
*/
function multi_array_search($array, $search)
{
// Create the result array
$result = array();
// Iterate over each array element
foreach ($array as $key => $value)
{
// Iterate over each search condition
foreach ($search as $k => $v)
{
// If the array element does not meet the search condition then continue to the next element
if (!isset($value[$k]) || $value[$k] != $v)
{
continue 2;
}
}
// Add the array element's key to the result array
$result[] = $key;
}
// Return the result array
return $result;
}
// Output the result
print_r(multi_array_search($list_of_phones, array()));
// Array ( [0] => 0 [1] => 1 )
// Output the result
print_r(multi_array_search($list_of_phones, array('Manufacturer' => 'Apple')));
// Array ( [0] => 0 )
// Output the result
print_r(multi_array_search($list_of_phones, array('Manufacturer' => 'Apple', 'Model' => 'iPhone 6')));
// Array ( )
As the output shows, this function will return an array of all keys with elements which meet all the search criteria.
I ended up doing the following. It's not pretty, but works very well. For anyone reading, feel free to update with a DRYer answer:
// Variables for this example
$carrier = 'Verizon';
$model = 'Droid X2';
$manufacturer = 'Motorola';
// The foreach loop goes through each key/value of $list_of_phones and checks
// if the given value is found in that particular array. If it is, it then checks
// a second parameter (model), and so on.
foreach ($list_of_phones as $key => $object)
{
if ( array_search($carrier, $object) )
{
if ( array_search($model, $object) )
{
if ( array_search($manufacturer, $object) )
{
// Return the phone from the $list_of_phones array
$phone = $list_of_phones[$key];
}
}
}
}
Works like a charm.
You can use array_filter(), which allows you to do as many checks on the contents as you need at the same time...
$output = array_filter($data_info_array, function ($data) {
return $data['score'] == 50 && $data['name'] == 'Bob';
});
This will give you a list of the matches, so you may need to do [0] (and check if only 1 is returned) if you need a single match.
You can build your search query as an array and compare the intersection of each item with it.
$search = ['score' => '50', 'name' => 'Bob'];
foreach($data_info_array as $k => $v) {
if ( $search === array_intersect($v, $search) ) {
echo $k;
break;
}
}
@mickmackusa noticed it is safer to use array_intersect_assoc() here. He's right because when the multi-dimensional array items are unpredictable, nothing forbids to have items like that:
['miaou' => '50', 'graou' => 'Bob', 'score' => '50', 'name' => 'Bob']
where the searched values are also present but for other keys. In this case array_intersect() returns all correct values (with their corresponding keys of course) regardless the keys in $search, and the comparison with the search array will return false.
But using array_intersect_assoc(), you ensure that only values for keys in $search are taken in account.
Conclusion: If you let yourself be lulled into sleep by the seeming monotony of multidimensional array items, you won't be immune to surprise when unexpected variations arise.