PHP: Get key from array? - php

I am sure that this is super easy and built-in function in PHP, but I have yet not seen it.
Here's what I am doing for the moment:
foreach($array as $key => $value) {
echo $key; // Would output "subkey" in the example array
print_r($value);
}
Could I do something like the following instead and thereby save myself from writing "$key => $value" in every foreach loop? (psuedocode)
foreach($array as $subarray) {
echo arrayKey($subarray); // Will output the same as "echo $key" in the former example ("subkey"
print_r($value);
}
Thanks!
The array:
Array
(
[subKey] => Array
(
[value] => myvalue
)
)

You can use key():
<?php
$array = array(
"one" => 1,
"two" => 2,
"three" => 3,
"four" => 4
);
while($element = current($array)) {
echo key($array)."\n";
next($array);
}
?>

Use the array_search function.
Example from php.net
$array = array(0 => 'blue', 1 => 'red', 2 => 'green', 3 => 'red');
$key = array_search('green', $array); // $key = 2;
$key = array_search('red', $array); // $key = 1;

$foo = array('a' => 'apple', 'b' => 'ball', 'c' => 'coke');
foreach($foo as $key => $item) {
echo $item.' is begin with ('.$key.')';
}

$array = array(0 => 100, "color" => "red");
print_r(array_keys($array));

If it IS a foreach loop as you have described in the question, using $key => $value is fast and efficient.

If you want to be in a foreach loop, then foreach($array as $key => $value) is definitely the recommended approach. Take advantage of simple syntax when a language offers it.

Another way to use key($array) in a foreach loop is by using next($array) at the end of the loop, just make sure each iteration calls the next() function (in case you have complex branching inside the loop)

Try this
foreach(array_keys($array) as $nmkey)
{
echo $nmkey;
}

Here is a generic solution that you can add to your Array library. All you need to do is supply the associated value and the target array!
PHP Manual: array_search() (similiar to .indexOf() in other languages)
public function getKey(string $value, array $target)
{
$key = array_search($value, $target);
if ($key === null) {
throw new InvalidArgumentException("Invalid arguments provided. Check inputs. Must be a (1) a string and (2) an array.");
}
if ($key === false) {
throw new DomainException("The search value does not exists in the target array.");
}
return $key;
}

Related

How to make a associative array from other associative array?

I need some help with another PHP problem I am working on. I won't be posting the exact question, as I'd prefer to try and apply the knowledge I get from here to solve my problem.
First:
I have an associative array. I must loop through the array to find the array values which have keys that begin with a specific string and push both the key and value to an output array.
eg:
- Loop through the below array & push all elements which have a key beginning with "edible_" to an output array:
$assoc_array = array(
'edible_fruit' => 'apple',
'animal' => 'cat',
'edible_veg' => 'pumpkin',
'number' => '23',
'city' => 'Cape Town',
'edible_berry' => 'blueberry',
'color' => 'blue'
);
Would this work?
$result = array();
foreach ($assoc_array as $key => $value) {
if (substr($key, 0, 7) == "edible_") {
array_push($result, $value);
}
}
print_r($result);
Second:
How would I remove "edible_" from the output array's keys? With this second bit I have no idea where to even begin!
Third:
I've managed to figure out the above with all your help, thank you! Now I just need to find out how I would print each element on a new line with a date & timestamp at the end of each line? I've got this (doesn't seem to be working):
while (list($key, $value) = each($output)) {
print_r("$key => $value" . date("y/m/d G.i:s", time()) . "<br>");
}
First of your code will work.
To remove edible_ from the key you could use explode() -
$keyParts = explode('_', $key);
$newKey = $keyParts[1];
You will have to add the new keys to the array, which you're not doing now.
foreach ($assoc_array as $key => $value) {
if (substr($key, 0, 7) == "edible_") {
$keyParts = explode('_', $key);
$newKey = $keyParts[1];
$result[$newKey] = $value;
}
}
This would be my approach:
foreach($assoc_array as $key => $value) {
if(preg_match("/^edible_/",$key)) {
$result[preg_replace("/^edible_/","",$key)] = $value;
}
}
use preg_match to check if the key starts with what you are looking for and use preg_replace to remove the string from the beginning (^) of the key :)
Input ($assoc_array):
Array
(
[edible_fruit] => apple
[animal] => cat
[edible_veg] => pumpkin
[number] => 23
[city] => Cape Town
[edible_berry] => blueberry
[color] => blue
)
Output ($result):
Array
(
[fruit] => apple
[veg] => pumpkin
[berry] => blueberry
)
First: yes, that would work, however I would rewrite it a bit:
foreach ($assoc_array as $key => $value) {
if (strpos($key, 'edible_') === 0) {
$result[] = $value;
}
}
Regarding Second: You are asking how to remove the key from the output array. However you did not even push the key into the output array, you only pushed the value. If you'd like to also push the key, you should do it like this:
$result[$key] = $value;
But since you haven't done that, there's no need to remove the key.
If you however meant removing the edible_ part of the key from the $assoc_array, you'd just need to add a line to the loop and pass the key by reference by adding a &:
foreach ($assoc_array as &$key => $value) {
if (strpos($key, 'edible_') === 0) {
$key = str_replace('edible_', '', $key)
$result[] = $value;
}
}
Edit: As OP told me in comments, she wants to push the key without the edible part. So just do it like this:
foreach ($assoc_array as $key => $value) {
if (strpos($key, 'edible_') === 0) {
$key = str_replace('edible_', '', $key)
$result[$key] = $value;
}
}
This should work for you:
First I remove all elements, which doesn't have edible_ at the start of the key with array_diff_ukey(). After this I simply array_combine() the elements with they keys, where I remove the prefix with array_map() and substr().
<?php
$assoc_array = array('edible_fruit'=>'apple', 'animal'=>'cat', 'edible_veg'=>'pumpkin', 'number'=>'23', 'city'=>'Cape Town', 'edible_berry'=>'blueberry', 'color'=>'blue');
//remove elemnts
$result = array_diff_ukey($assoc_array, ["edible_" => ""], function($k1, $k2){
return substr($k1, 0, 7) == $k2;
});
//change keys
$result = array_combine(
array_map(function($v){
return substr($v, 7);
}, array_keys($result)),
$result);
print_r($result);
?>
output:
Array ( [fruit] => apple [veg] => pumpkin [berry] => blueberry )
You can loop through the array and search if the key has the string that you can eliminate and make your $newArray
<?php
$assoc_array = array('edible_fruit'=>'apple', 'animal'=>'cat', 'edible_veg'=>'pumpkin', 'number'=>'23', 'city'=>'Cape Town', 'edible_berry'=>'blueberry', 'color'=>'blue');
$search = 'edible_';
$newArray = array();
#First and Second Step
foreach($assoc_array as $key => $value) {
if(strpos($key, "edible_") === 0) {
$newArray[substr($key, 7)] = $value;
}
}
print_r($newArray);
echo "<br>\n";
#Third Step
foreach($newArray as $key => $value) {
echo "$key => $value " . date("y/m/d G.i:s", time()) . "<br>\n";
}
Output:
#First and Second Step
Array ( [fruit] => apple [veg] => pumpkin [berry] => blueberry )
#Third Step
fruit => apple 15/04/10 3.02:16
veg => pumpkin 15/04/10 3.02:16
berry => blueberry 15/04/10 3.02:16

Is there are way to start with a specific value in foreach loop of PHP?

Let say I have an array as follows:
$my_array = array(
"fruit1" => "apple",
"fruit2" => "orange",
"notfruit" => "hamburger",
"fruit3" => "banana"
)
Is there a way I can choose to start with $my_array['notfruit'] in an foreach loop of PHP? I don't care the sequence except the first one.
Currently I can think of copying the whole piece of code once and change it specifically for $my_array['notfruit'], then unset it from the array to use foreach loop to go through the remaining. i.e.
echo $my_array['notfruit']."is not fruit. Who put that in the array?";
unset ($my_array['notfruit']);
foreach ($my_array as $values) {
echo $values." is fruit. I love fruit so I like ".$values;
}
It works but it sounds stupid, and can cause problem if the content in the foreach loop is long.
You can filter out any element with a key that doesn't begin with fruit pretty easily
$fruits = array_filter(
$my_array,
function ($key) {
return fnmatch('fruit*', $key);
},
ARRAY_FILTER_USE_KEY
);
var_dump($fruits);
though using array_filter() with the keys like this does require PHP >= 5.6
EDIT
For earlier versions of PHP, you can swap the keys/values before filtering; then flip them again afterwards
$fruits = array_flip(
array_filter(
array_flip($my_array),
function ($value) {
return fnmatch('fruit*', $value);
}
)
);
var_dump($fruits);
Short answer, no.
You can, however pull whatever functionality you intended to have in the foreach into a funcion, then call the funcion specifically for the notfruit value, then run the foreach.
function foo($val) {
// do stuff with $val
}
$my_array = array(
"fruit1" => "apple",
"fruit2" => "orange",
"notfruit" => "hamburger",
"fruit3" => "banana"
)
foo($my_array['nofriut']);
unset($my_array['nofruit']);
foreach($my_array as $val) {
foo($val);
}
EDIT
Or if your case is as simple as your updated question, simply check if the key is nofruit
foreach($my_array as $key => $val) {
if($key === "nofruit") {
echo "$val is not fruit. Who put that in the array?";
} else {
echo "$val is fruit. I love fruit so I like $val";
}
}
You can use addition in arrays, which is more performant than array_unshift.
So unset it, and then add it back:
unset($my_array['notfruit']);
$my_array = array('notfruit' => 'hamburger') + $my_array;
var_dump($my_array);
Or if you want to use a variable:
$keyToMove = 'notfruit';
$val = $my_array[$keyToMove];
unset($my_array[$keyToMove]);
$newArray = array($keyToMove => $val) + $my_array;
var_dump($newArray);
Obviously you can put this all in a loop, applying it to any that you need to move.
Try this..
<?php
$my_array = array(
"fruit1" => "apple",
"fruit2" => "orange",
"notfruit" => "hamburger",
"fruit3" => "banana"
);
$new_value['notfruit'] = $my_array['notfruit'];
unset($my_array['notfruit']);
$newarray=array_merge($new_value,$my_array);
print_r($newarray);
?>
Result:Array ( [notfruit] => hamburger [fruit1] => apple [fruit2] => orange [fruit3] => banana )
There is too many options.
1 . Using array_merge or array_replace (i think that it is the simplest way)
$my_array = array_merge(['notfruit' => null], $my_array);
// $my_array = array_replace(['notfruit' => null], $my_array);
foreach ($my_array as $key => $value) {
var_dump($key, $value);
}
2 . Using generators.
$my_array = array(
"fruit1" => "apple",
"fruit2" => "orange",
"notfruit" => "hamburger",
"fruit3" => "banana"
);
$generator = function($my_array){
yield 'notfruit'=>$my_array['notfruit'];
unset($my_array['notfruit']);
foreach($my_array as $key => $value)
yield $key => $value;
};
foreach ($generator($my_array) as $key=>$value){
var_dump($key, $value);
}
3 . Readding value
$no_fruit = $my_array['nofruit'];
unset($my_array['nofruit']);
$my_array['nofruit'] = $no_fruit;
$my_array = array_reverse($my_array, true);
foreach ($my_array as $key=>$value){
var_dump($key, $value);
}
4 . Using infinitive iterator
$infinate = new InfiniteIterator(new ArrayIterator($my_array));
$limit_iterator = new LimitIterator(
$infinate,
array_search('notfruit', array_keys($my_array)), // position of desired key
count($my_array));
foreach ($limit_iterator as $key => $value) {
var_dump($key, $value);
}
$no_fruit = $my_array['nofruit']; // grab the value
unset($my_array['nofruit']); // remove value from array
array_unshift($my_array, $no_fruit); // add value at the beginning
or
$no_fruit = $my_array['nofruit']; // grab the value
unset($my_array['nofruit']); // remove value from array
$my_array = array('nofruit' => $no_fruit ) + $my_array; // add value at the beginning

Change array key without changing order

You can "change" the key of an array element simply by setting the new key and removing the old:
$array[$newKey] = $array[$oldKey];
unset($array[$oldKey]);
But this will move the key to the end of the array.
Is there some elegant way to change the key without changing the order?
(PS: This question is just out of conceptual interest, not because I need it anywhere.)
Tested and works :)
function replace_key($array, $old_key, $new_key) {
$keys = array_keys($array);
if (false === $index = array_search($old_key, $keys, true)) {
throw new Exception(sprintf('Key "%s" does not exist', $old_key));
}
$keys[$index] = $new_key;
return array_combine($keys, array_values($array));
}
$array = [ 'a' => '1', 'b' => '2', 'c' => '3' ];
$new_array = replace_key($array, 'b', 'e');
Something like this may also work:
$langs = array("EN" => "English",
"ZH" => "Chinese",
"DA" => "Danish",
"NL" => "Dutch",
"FI" => "Finnish",
"FR" => "French",
"DE" => "German");
$json = str_replace('"EN":', '"en":', json_encode($langs));
print_r(json_decode($json, true));
OUTPUT:
Array
(
[en] => English
[ZH] => Chinese
[DA] => Danish
[NL] => Dutch
[FI] => Finnish
[FR] => French
[DE] => German
)
One way would be to simply use a foreach iterating over the array and copying it to a new array, changing the key conditionally while iterating, e.g. if $key === 'foo' then dont use foo but bar:
function array_key_rename($array, $oldKey, $newKey)
{
$newArray = [];
foreach ($array as $key => $value) {
$newArray[$key === $oldKey ? $newKey : $key] = $value;
}
return $newArray;
}
Another way would be to serialize the array, str_replace the serialized key and then unserialize back into an array again. That isnt particular elegant though and likely error prone, especially when you dont only have scalars or multidimensional arrays.
A third way - my favorite - would be you writing array_key_rename in C and proposing it for the PHP core ;)
Check keys existence before proceeding…
Otherwise the result can be catastrophic if the new key already exists... or unnecessary processing time/memory consumption if the key to be replaced does not exist.
function array_rename_key( array $array, $old_key, $new_key ) {
// if $new_key already exists, or if $old_key doesn't exists
if ( array_key_exists( $new_key, $array ) || ! array_key_exists( $old_key, $array ) ) {
return $array;
}
$new_array = [];
foreach ( $array as $k => $v ) {
$new_array[ $k === $old_key ? $new_key : $k ] = $v;
}
return $new_array;
}
Do a double flip! At least that is all I can think of:
$array=("foo"=>"bar","asdf"=>"fdsa");
$array=array_flip($array);
$array["bar"]=>'newkey';
$array=array_flip($array);
We are using this function for changing multiple array keys within an array keeping the order:
function replace_keys($array, $keys_map) {
$keys = array_keys($array);
foreach($keys_map as $old_key=>$new_key){
if (false === $index = array_search($old_key, $keys)) {
continue;
}
$keys[$index] = $new_key;
}
return array_combine($keys, array_values($array));
}
You can pass an array as $keys_map, like this:
$keys_map=array("old_key_1"=>"new_key_1", "old_key_2"=>"new_key_2",...)
This solution is based on Kristian one.
If possible, one can also put the key to change at the end of the array in the moment of creation :
$array=array('key1'=>'value1','key2'=>'value2','keytochange'=>'value');
$x=$array['keytochange'];
unset($array['keytochange']);
$array['newkey']=$x;
You could use array_combine. It merges an array for keys and another for values...
For instance:
$original_array =('foo'=>'bar','asdf'=>'fdsa');
$new_keys = array('abc', 'def');
$new_array = array_combine($new_keys, $original_array);

Retrieve array key passed on value PHP

I have the following array
$group= array(
[0] => 'apple',
[1] => 'orange',
[2] => 'gorilla'
);
I run the array group through an for each function and when the loop hits values of gorilla I want it to spit out the index of gorilla
foreach ($group as $key) {
if ($key == gorilla){
echo //<------ the index of gorilla
}
}
You can use array_search function to get the key for specified value:
$key = array_search('gorilla', $group);
foreach( $group as $index => $value) {
if ($value == "gorilla")
{
echo "The index is: $index";
}
}
array_search — Searches the array for a given value and returns the corresponding key if successful
<?php
$array = array(0 => 'blue', 1 => 'red', 2 => 'green', 3 => 'red');
$key = array_search('green', $array); // $key = 2;
$key = array_search('red', $array); // $key = 1;
?>
foreach($group as $key => $value) {
if ($value=='gorilla') {
echo $key;
}
}
The foreach($c as $k => $v) syntax is similar to the foreach($c as $v) syntax, but it puts the corresponding keys/indices in $k (or whatever variable is placed there) for each value $v in the collection.
However, if you're just looking for the index of a single value, array_search() may be simpler. If you're looking for indices for many values, stick with the foreach.
Try this:
foreach ($group as $key => $value)
{
echo "$key points to $value";
}
foreach documentation on php.net

Iterating over a complex Associative Array in PHP

Is there an easy way to iterate over an associative array of this structure in PHP:
The array $searches has a numbered index, with between 4 and 5 associative parts. So I not only need to iterate over $searches[0] through $searches[n], but also $searches[0]["part0"] through $searches[n]["partn"]. The hard part is that different indexes have different numbers of parts (some might be missing one or two).
Thoughts on doing this in a way that's nice, neat, and understandable?
Nest two foreach loops:
foreach ($array as $i => $values) {
print "$i {\n";
foreach ($values as $key => $value) {
print " $key => $value\n";
}
print "}\n";
}
I know it's question necromancy, but iterating over Multidimensional arrays is easy with Spl Iterators
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
foreach($iterator as $key=>$value) {
echo $key.' -- '.$value.'<br />';
}
See
http://php.net/manual/en/spl.iterators.php
Looks like a good place for a recursive function, esp. if you'll have more than two levels of depth.
function doSomething(&$complex_array)
{
foreach ($complex_array as $n => $v)
{
if (is_array($v))
doSomething($v);
else
do whatever you want to do with a single node
}
}
You should be able to use a nested foreach statment
from the php manual
/* foreach example 4: multi-dimensional arrays */
$a = array();
$a[0][0] = "a";
$a[0][1] = "b";
$a[1][0] = "y";
$a[1][1] = "z";
foreach ($a as $v1) {
foreach ($v1 as $v2) {
echo "$v2\n";
}
}
Can you just loop over all of the "part[n]" items and use isset to see if they actually exist or not?
I'm really not sure what you mean here - surely a pair of foreach loops does what you need?
foreach($array as $id => $assoc)
{
foreach($assoc as $part => $data)
{
// code
}
}
Or do you need something recursive? I'd be able to help more with example data and a context in how you want the data returned.
Consider this multi dimentional array, I hope this function will help.
$n = array('customer' => array('address' => 'Kenmore street',
'phone' => '121223'),
'consumer' => 'wellington consumer',
'employee' => array('name' => array('fname' => 'finau', 'lname' => 'kaufusi'),
'age' => 32,
'nationality' => 'Tonga')
);
iterator($n);
function iterator($arr){
foreach($arr as $key => $val){
if(is_array($val))iterator($val);
echo '<p>key: '.$key.' | value: '.$val.'</p>';
//filter the $key and $val here and do what you want
}
}

Categories