Is there a fast way to return a key when you know its value in PHP?
For example, if you have:
$Numbers = (object) array ( "0" => 0, "1" => 1, "2" => 3, "3" => 7, "4" => 13 );
is there a way to return:
echo re(13); // Print 4
One way I could think of is to build a function specifically for this, but I was wondering if there is a better way.
There is array_search:
$key = array_search(13, (array) $Numbers);
See http://ua2.php.net/array_search
As several other people have mentioned, array_search does what you asked. But if you want an array of ALL the keys that contain the value instead of only the first, you can use array_keys.
print_r(array_keys($Numbers, 13)); // print Array ( [0] => 4 )
http://www.php.net/manual/en/function.array-keys.php
if you are certain that you have unique keys:
$flipped = array_flip($array);
$key = $flipped[$knownValue];
return $key;
Otherwise, use array_search:
return array_search($knownValue, $array);
The first approach may be better if you do a number of lookups, and have unique values. The second approach returns the first matching key in case of multiple values.
http://php.net/array_search
echo array_search($valToSearch, (array) $Numbers);
http://php.net/manual/en/function.array-search.php
Related
This question already has answers here:
Generate an associative array from an array of rows using one column as keys and another column as values
(3 answers)
Closed 5 months ago.
The Microsoft QnAMaker API is returning a JSON key/value array (Metadata) in the following format:
$array = [[
"name" => "someName1",
"value" => "someValue1",
],
[
"name" => "someName2",
"value" => "someValue2",
],
..etc..
];
How do i transform it to be in the following more usable format:
$array = [
"someName1" => "someValue1",
"someName2" => "someValue2",
..etc..
];
I know I can do it using a loop... Is there a way to leverage on built in functions?
If a loop is the only way, how would you write it and why (performance/readibility/etc.)?
If it looks JSONish, array_column helps. Simply:
<?php
var_export(array_column($array, 'value', 'name'));
Output:
array (
'someName1' => 'someValue1',
'someName2' => 'someValue2',
)
This uses a combination of array_map() to re-map each element and then array_merge() to flatten the results...
print_r(array_merge(...array_map(function($data)
{ return [ $data['name'] => $data['value']]; }
, $array)));
It's not very elegant and would be interesting to see other ideas around this.
Which gives...
Array
(
[someName1] => someValue1
[someName2] => someValue2
)
There isn't really a way besides a loop, so just loop through the array, and create a new array the way you need it.
$new_array = [];
foreach($array as $row) {
$new_array[$row['name']] = $row['value'];
}
print_r($new_array);
There may be a few functions you can tie together to do what you want, but in general, the loop would probably be more readable and easier in overall.
As my previous answer was a dupe of GrumpyCroutons, I thought I'd rewrite with many array functions for good measure. (But don't use this, just do a simple foreach).
<?php
array_walk($array, function($v) use (&$result) {
$result[array_shift($v)] = array_values($v)[0];
});
var_export($result);
Output:
array (
'someName1' => 'someValue1',
'someName2' => 'someValue2',
)
This works:
$res = [];
array_walk($array, function(&$e) use(&$res) {
$res[$e['name']] = $e['value'];
unset($e); // this line adds side effects and it could be deleted
});
var_dump($res);
Output:
array(2) {
["someName1"]=> string(10) "someValue1"
["someName2"]=> string(10) "someValue2"
}
You can simply use array_reduce:
<?php
$output = array_reduce($array, function($a, $b) {
$a[$b['name']] = $b['value'];
return $a;
});
var_export($output);
Output:
array (
'someName1' => 'someValue1',
'someName2' => 'someValue2',
)
While getting a shift on (a non-foreach):
<?php
$c = $array;
while($d = array_shift($c))
$e[array_shift($d)] = array_shift($d);
var_export($e);
Output:
array (
'someName1' => 'someValue1',
'someName2' => 'someValue2',
)
Although it suggests in the comments in the manual that shifting is more expensive than popping. You could replace the initial assignment to $c above with an array_reverse and the while-shift with a while-pop.
However, either approach is probably lousy compared to a foreach, but here for who knows whos amusement.
Is there a possibility in PHP to get an array element by it's value. What I wan't to do is to update an element without knowing the key but nowing it's value:
$translations = array(
"en" => 123,
"de" => 456,
"es" => 789,
"fr" => 901
);
i know that what i wan't to do can be done with an foreach loop:
foreach($translations as $lang=>$id):
if($id == 123) $translations[$lang] = 0;
endforeach;
But is there any possibility to avoid this loop and to automatically set it?
You are looking for array_search():
if(false!==($key = array_search(123, $translations)))
{
$translations[$key] = 0;
}
-be aware that value can be non-unique, so array_search() will find only first key. If you need all of them, you'll have to either iterate through array with foreach or use something like array_walk()
You should use this :
$translations[array_search('123', $translations)] = 0;
Edit: use the solution proposed by Alma Do Mundo, he is right about checking the return value
You can do it in this way also.
Use array_keys function with search_values parameter. It will give you the array of keys which are having these values. Then you can update the original array based on the new array.
It will take care of all the duplicate values also.
$translations = array(
"en" => 123,
"de" => 456,
"es" => 789,
"fr" => 901,
"it" => 123
);
$arr=array_keys($translations,$seach_value);
if(count($arr)){
foreach($arr as $key => $value){
$translations[$value]=$new_value;
}
}
In php I'm willing to check the existence of indexes that match with another values in array.
$indexes = array("index", "id", "view");
$fields = array(
"index" => 5,
"id" => 7,
"form" => 10,
"date" => 10,
);
MY ideal result is, in this case, to get "form" and "date". Any idea?
Try
$fields_keys = array_keys($fields);
$fields_unique = array_diff($fields_keys, $indexes);
The result will be an array of all keys in $fields that are not in $indexes.
You can try this.
<?php
$indexes = array("index", "id", "view");
$fields = array(
"index" => 5,
"id" => 7,
"form" => 10,
"date" => 10,
);
$b = array_diff(array_keys($fields), $indexes);
print_r($b);
You can use array_keys function to retrieve keys of a array
Eg:
$array = array(0 => 100, "color" => "red");
print_r(array_keys($array));
Outputs
Array
(
[0] => 0
[1] => color
)
PHP Documentation
Your question is a little unclear but I think this is what you're going for
array_keys(array_diff_key($fields, array_fill_keys($indexes, null)));
#=> Array( 0=>"form", 1=>"date" )
See it work here on tehplayground.com
array_keys(A) returns the keys of array A as a numerically-indexed array.
array_fill_keys(A, value) populates a new array using array A as keys and sets each key to value
array_diff_key(A,B) returns an array of keys from array A that do not exist in array B.
Edit turns on my answer got more complicated as I understood the original question more. There are better answers on this page, but I still think this is an interesting solution.
There is probably a slicker way than this but it will get you started:
foreach(array_keys($fields) as $field) {
if(!in_array($field, $indexes)) {
$missing[] = $field;
}
}
Now you will have an array that holds form and date.
array(
[0]
name => 'joe'
size => 'large'
[1]
name => 'bill'
size => 'small'
)
I think i'm being thick, but to get the attributes of an array element if I know the value of one of the keys, I'm first looping through the elements to find the right one.
foreach($array as $item){
if ($item['name'] == 'joe'){
#operations on $item
}
}
I'm aware that this is probably very poor, but I am fairly new and am looking for a way to access this element directly by value. Or do I need the key?
Thanks,
Brandon
If searching for the exact same array it will work, not it you have other values in it:
<?php
$arr = array(
array('name'=>'joe'),
array('name'=>'bob'));
var_dump(array_search(array('name'=>'bob'),$arr));
//works: int(1)
$arr = array(
array('name'=>'joe','a'=>'b'),
array('name'=>'bob','c'=>'d'));
var_dump(array_search(array('name'=>'bob'),$arr));
//fails: bool(false)
?>
If there are other keys, there is no other way then looping as you already do. If you only need to find them by name, and names are unique, consider using them as keys when you create the array:
<?php
$arr = array(
'joe' => array('name'=>'joe','a'=>'b'),
'bob' => array('name'=>'bob','c'=>'d'));
$arr['joe']['a'] = 'bbb';
?>
Try array_search
$key = array_search('joe', $array);
echo $array[$key];
If you need to do operations on name, and name is unique within your array, this would be better:
array(
'joe'=> 'large',
'bill'=> 'small'
);
With multiple attributes:
array(
'joe'=>array('size'=>'large', 'age'=>32),
'bill'=>array('size'=>'small', 'age'=>43)
);
Though here you might want to consider a more OOP approach.
If you must use a numeric key, look at array_search
You can stick to your for loop. There are not big differences between it and other methods – the array has always to be traversed linearly. That said, you can use these functions to find array pairs with a certain value:
array_search, if you're there's only one element with that value.
array_keys, if there may be more than one.
How can I get the last key of an array?
A solution would be to use a combination of end and key (quoting) :
end() advances array 's internal pointer to the last element, and returns its value.
key() returns the index element of the current array position.
So, a portion of code such as this one should do the trick :
$array = array(
'first' => 123,
'second' => 456,
'last' => 789,
);
end($array); // move the internal pointer to the end of the array
$key = key($array); // fetches the key of the element pointed to by the internal pointer
var_dump($key);
Will output :
string 'last' (length=4)
i.e. the key of the last element of my array.
After this has been done the array's internal pointer will be at the end of the array. As pointed out in the comments, you may want to run reset() on the array to bring the pointer back to the beginning of the array.
Although end() seems to be the easiest, it's not the fastest. The faster, and much stronger alternative is array_slice():
$lastKey = key(array_slice($array, -1, 1, true));
As the tests say, on an array with 500000 elements, it is almost 7x faster!
Since PHP 7.3 (2018) there is (finally) function for this:
http://php.net/manual/en/function.array-key-last.php
$array = ['apple'=>10,'grape'=>15,'orange'=>20];
echo array_key_last ( $array )
will output
orange
I prefer
end(array_keys($myarr))
Just use : echo $array[count($array) - 1];
Dont know if this is going to be faster or not, but it seems easier to do it this way, and you avoid the error by not passing in a function to end()...
it just needed a variable... not a big deal to write one more line of code, then unset it if you needed to.
$array = array(
'first' => 123,
'second' => 456,
'last' => 789,
);
$keys = array_keys($array);
$last = end($keys);
As of PHP7.3 you can directly access the last key in (the outer level of) an array with array_key_last()
The definitively puts much of the debate on this page to bed. It is hands-down the best performer, suffers no side effects, and is a direct, intuitive, single-call technique to deliver exactly what this question seeks.
A rough benchmark as proof: https://3v4l.org/hO1Yf
array_slice() + key(): 1.4
end() + key(): 13.7
array_key_last(): 0.00015
*test array contains 500000 elements, microtime repeated 100x then averaged then multiplied by 1000 to avoid scientific notation. Credit to #MAChitgarha for the initial benchmark commented under #TadejMagajna's answer.
This means you can retrieve the value of the final key without:
moving the array pointer (which requires two lines of code) or
sorting, reversing, popping, counting, indexing an array of keys, or any other tomfoolery
This function was long overdue and a welcome addition to the array function tool belt that improves performance, avoids unwanted side-effects, and enables clean/direct/intuitive code.
Here is a demo:
$array = ["a" => "one", "b" => "two", "c" => "three"];
if (!function_exists('array_key_last')) {
echo "please upgrade to php7.3";
} else {
echo "First Key: " , key($array) , "\n";
echo "Last Key: " , array_key_last($array) , "\n";
next($array); // move array pointer to second element
echo "Second Key: " , key($array) , "\n";
echo "Still Last Key: " , array_key_last($array);
}
Output:
First Key: a
Last Key: c // <-- unaffected by the pointer position, NICE!
Second Key: b
Last Key: c // <-- unaffected by the pointer position, NICE!
Some notes:
array_key_last() is the sibling function of array_key_first().
Both of these functions are "pointer-ignorant".
Both functions return null if the array is empty.
Discarded sibling functions (array_value_first() & array_value_last()) also would have offered the pointer-ignorant access to bookend elements, but they evidently failed to garner sufficient votes to come to life.
Here are some relevant pages discussing the new features:
https://laravel-news.com/outer-array-functions-php-7-3
https://kinsta.com/blog/php-7-3/#array-key-first-last
https://wiki.php.net/rfc/array_key_first_last
p.s. If anyone is weighing up some of the other techniques, you may refer to this small collection of comparisons: (Demo)
Duration of array_slice() + key(): 0.35353660583496
Duration of end() + key(): 6.7495584487915
Duration of array_key_last(): 0.00025749206542969
Duration of array_keys() + end(): 7.6123380661011
Duration of array_reverse() + key(): 6.7875385284424
Duration of array_slice() + foreach(): 0.28870105743408
As of PHP >= 7.3 array_key_last() is the best way to get the last key of any of an array. Using combination of end(), key() and reset() just to get last key of an array is outrageous.
$array = array("one" => bird, "two" => "fish", 3 => "elephant");
$key = array_key_last($array);
var_dump($key) //output 3
compare that to
end($array)
$key = key($array)
var_dump($key) //output 3
reset($array)
You must reset array for the pointer to be at the beginning if you are using combination of end() and key()
Try using array_pop and array_keys function as follows:
<?php
$array = array(
'one' => 1,
'two' => 2,
'three' => 3
);
echo array_pop(array_keys($array)); // prints three
?>
It is strange, but why this topic is not have this answer:
$lastKey = array_keys($array)[count($array)-1];
I would also like to offer an alternative solution to this problem.
Assuming all your keys are numeric without any gaps,
my preferred method is to count the array then minus 1 from that value (to account for the fact that array keys start at 0.
$array = array(0=>'dog', 1=>'cat');
$lastKey = count($array)-1;
$lastKeyValue = $array[$lastKey];
var_dump($lastKey);
print_r($lastKeyValue);
This would give you:
int(1)
cat
You can use this:
$array = array("one" => "apple", "two" => "orange", "three" => "pear");
end($array);
echo key($array);
Another Solution is to create a function and use it:
function endKey($array){
end($array);
return key($array);
}
$array = array("one" => "apple", "two" => "orange", "three" => "pear");
echo endKey($array);
$arr = array('key1'=>'value1','key2'=>'value2','key3'=>'value3');
list($last_key) = each(array_reverse($arr));
print $last_key;
// key3
I just took the helper-function from Xander and improved it with the answers before:
function last($array){
$keys = array_keys($array);
return end($keys);
}
$arr = array("one" => "apple", "two" => "orange", "three" => "pear");
echo last($arr);
echo $arr(last($arr));
$array = array(
'something' => array(1,2,3),
'somethingelse' => array(1,2,3,4)
);
$last_value = end($array);
$last_key = key($array); // 'somethingelse'
This works because PHP moves it's array pointer internally for $array
The best possible solution that can be also used used inline:
end($arr) && false ?: key($arr)
This solution is only expression/statement and provides good is not the best possible performance.
Inlined example usage:
$obj->setValue(
end($arr) && false ?: key($arr) // last $arr key
);
UPDATE: In PHP 7.3+: use (of course) the newly added array_key_last() method.
Try this one with array_reverse().
$arr = array(
'first' => 01,
'second' => 10,
'third' => 20,
);
$key = key(array_reverse($arr));
var_dump($key);
Try this to preserve compatibility with older versions of PHP:
$array_keys = array_keys( $array );
$last_item_key = array_pop( $array_keys );