I have a foreach loop in php to iterate an associative array. Within the loop, instead of increamenting a variable I want to get numeric index of current element. Is it possible.
$arr = array('name'=>'My name','creditcard'=>'234343435355','ssn'=>1450);
foreach($arr as $person){
// want index here
}
I usually do this to get index:
$arr = array('name'=>'My name','creditcard'=>'234343435355','ssn'=>1450);
$counter =0;
foreach($arr as $person){
// do a stuff
$counter++;
}
Use this syntax to foreach to access the key (as $index) and the value (as $person)
foreach ($arr as $index => $person) {
echo "$index = $person";
}
This is explained in the PHP foreach documentation.
Why would you need a numeric index inside associative array? Associative array maps arbitrary values to arbitrary values, like in your example, strings to strings and numbers:
$assoc = [
'name'=>'My name',
'creditcard'=>'234343435355',
'ssn'=>1450
];
Numeric arrays map consecutive numbers to arbitrary values. In your example if we remove all string keys, numbering will be like this:
$numb = [
0=>'My name',
1=>'234343435355',
2=>1450
];
In PHP you don't have to specify keys in this case, it generates them itself.
Now, to get keys in foreach statement, you use the following form, like #MichaelBerkowski already shown you:
foreach ($arr as $index => $value)
If you iterate over numbered array, $index will have number values. If you iterate over assoc array, it'll have values of keys you specified.
Seriously, why I am even describing all that?! It's common knowledge straight from the manual!
Now, if you have an associative array with some arbitrary keys and you must know numbered position of the values and you don't care about keys, you can iterate over result of array_values on your array:
foreach (array_values($assoc) as $value) // etc
But if you do care about keys, you have to use additional counter, like you shown yourself:
$counter = 0;
foreach ($assoc as $key => $value)
{
// do stuff with $key and $value
++$counter;
}
Or some screwed functional-style stuff with array_reduce, doesn't matter.
Related
I have a two-dimensional array and look for a way to find the all double entries. E.g. if the array is of the form
$a = array(
array('a','b','c'),
array('d','a','e'),
array('d','c','b')
)
the function should return the list
array(array(0,0),array(1,1)) // Since $a[0,0]=$a[1,1]
array(array(0,1),array(2,2)) // Since $a[0,1]=$a[2,2]
array(array(0,2),array(2,1)) // Since $a[0,2]=$a[2,1]
array(array(1,0),array(2,0)) // Since $a[1,0]=$a[2,0]
array(1,2) // Unmatched
Is there an elegant/efficient way to implement this?
With a nested loop. Use the values as keys in the result and append the coordinates as arrays under those keys.
foreach ($a as $x => $inner) {
foreach ($inner as $y => $value) {
$result[$value][] = [$x, $y];
}
}
The $result will contain sets of coordinates for all the given values. You can group the results by size of set to identify which values are unmatched, pairs, or have even greater than two occurrences (if that's possible).
foreach ($result as $value => $set) {
$sets[count($set)][$value] = $set;
}
I'm trying to find a simpler way to create new arrays from existing arrays and values. There are two routines I'd like to optimize that are similar in construction. The form of the first one is:
$i = 0;
$new_array = array();
foreach ($my_array as $value) {
$new_array[$i][0] = $constant; // defined previously and unchanging
$new_array[$i][1] = $value; // different for each index of $my_array
$i++;
}
The form of the second one has not one but two different values per constant; notice that $value comes before $key in the indexing:
$i = 0;
$new_array = array();
foreach ($my_array as $key => $value) {
$new_array[$i][0] = $constant; // defined previously and unchanging
$new_array[$i][1] = $value; // different for each index of $my_array
$new_array[$i][2] = $key; // different for each index of $my_array
$i++;
}
Is there a way to optimize these procedures with shorter and more efficient routines using the array operators of PHP? (There are many, of course, and I can't find one that seems to fit the bill.)
I believe a combination of Wouter Thielen's suggestions regarding the other solutions actually holds the best answer for me.
For the first case I provided:
$new_array = array();
// $my_array is numeric, so $key will be index count:
foreach ($my_array as $key => $value) {
$new_array[$key] = array($constant, $value);
};
For the second case I provided:
// $my_array is associative, so $key will initially be a text index (or similar):
$new_array = array();
foreach ($my_array as $key => $value) {
$new_array[$key] = array($constant, $value, $key);
};
// This converts the indexes to consecutive integers starting with 0:
$new_array = array_values($new_array);
it is shorter, when you use the array-key instead of the $i-counter
$new_array = array();
foreach ($my_array as $key => $value) {
$new_array[$key][0] = $constant; // defined previously and unchanging
$new_array[$key][1] = $value; // different for each index of $my_array
}
Use array_map:
$new_array = array_map(function($v) use ($constant) {
return array($constant, $v);
}, $my_array);
If you want to use the keys too, for your second case:
$new_array = array_map(function($k, $v) use ($constant) {
return array($constant, $v, $k);
}, array_keys($my_array), $my_array);
Assuming the $constant variable is defined in the caller's scope, you'll need to use use ($constant) to pass it into the function's scope.
array_walk is similar, but modifies the array you pass to it, so if you want to update $my_array itself, use array_walk. Your second case then becomes this:
array_walk($my_array, function(&$val, $key) use($constant) {
$val = array($constant, $val, $key);
});
In both examples above for the second case, you'll end up with an associative array (i.e. with the keys still being the keys for the array). If you want to convert this into a numerically indexed array, use array_values:
$numerically_indexed = array_values($associative);
I asked a question similar to this a few days ago, check it out:
PHP - Fastest way to convert a 2d array into a 3d array that is grouped by a specific value
I think that you have an optimal way when it comes to dealing with large amount of data. For smaller amounts there is a better way as was suggested by the benchmarks in my question.
I think too that readability and understanding the code can also be an issue here and I find that things that you can understand are worth more later on than ideas that you do not really grasp as it generally takes a long time to understand them again as it can be quite confusing while debugging issues.
I would suggest, you take a look at the differences between JSON encoded arrays and serialised arrays as there can be major performance differences when working with the two. It seems that as it is now JSON encoded arrays are a more optimised format (faster) for holding and working with data however this will likely change with PHP 7. It would be useful to note that they are also more portable.
Further Reading:
Preferred method to store PHP arrays (json_encode vs serialize)
http://techblog.procurios.nl/k/n618/news/view/34972/14863/cache-a-large-array-json-serialize-or-var_export.html
for example:
$numbers = array(1, 2, 3, 4, 5);
foreach($numbers as $value)
{
echo $value;
}
what does as do, I assume it's a keyword because it is highlighted as one in my text editor. I checked the keyword list at http://www.php.net/manual/en/reserved.keywords.php and the as keyword was present. It linked to the foreach construct page, and from what I could tell didn't describe what the as keyword did. Does this as keyword have other uses or is it just used in the foreach construct?
It's used to iterate over Iterators, e.g. arrays. It reads:
foreach value in $numbers, assign the value to $value.
You can also do:
foreach ($numbers as $index => $value) {
}
Which reads:
foreach value in $numbers, assign the index/key to $index and the value to $value.
To demonstrate the full syntax, lets say we have the following:
$array = array(
0 => 'hello',
1 => 'world')
);
For the first iteration of our foreach loop, $index would be 0 and $value would be 'hello'. For the second iteration of our foreach loop, $index would be 1, and $value would be 'world'.
Foreach loops are very common. You may have seen them as for..in loops in other languages.
For the as keyword, you're saying:
for each value in $numbers AS $value
It's a bit awkward, I know. As far as I know, the as keyword is only used with foreach loops.
as is just part of the foreach syntax, it's used to specify the variables that are assigned during the iteration. I don't think it's used in any other context in PHP.
I've got an array containing values I wish to use as keys, such as:
$keys = array("first", "second", "third", "fourth");
The count and contents of these values will be changing dynamically within a loop. I want them to become the keys of a multidimensional array, but the count of the keys array will always be changing, so while this would work for that first array of keys:
$multidimensional[$keys[0]][$keys[1]][$keys[2]][$keys[3]] = "some value";
Later in the loop the keys may be something like:
$keys = array("first", "second", "gamma", "delta", "theta", "kappa");
So using this in the loop:
$multidimensional[$keys[0]][$keys[1]][$keys[2]][$keys[3]] = "some value";
Will not work, and needs to be dynamic too based on the count of the keys.
I've gone through each of the array functions in the PHP manual and can't seem to find something that fulfills this purpose. Am I totally overlooking something basic here? Maybe some curly brace magic?
There you go...
function setMultidimensionalValue($value, array $keys, array $multidimensional)
{
$node = &$multidimensional;
foreach ($keys as $key)
{
if (!isset($node[$key]))
$node[$key] = null;
$node = &$node[$key];
}
$node = $value;
return $multidimensional;
}
// Example of usage
$multidimensional = array();
var_dump(setMultidimensionalValue('value', array('first', 'second', 'third'), $multidimensional));
Hello,
I want to grab the ordinal number of an array key inside a foreach loop.
Example
<?php
$array = array("id" => 2, "username" => "foobar");
foreach($array as $value){
$array_key = search_array($value, $array);
//find the ordinal number of $array_key from $array here.
echo $value;
}
count returns the entire number of array keys in the array, i need to grab the ordinal number of the array key.
I hope you guys understand what i ask.
From what I understand, if an entry has a string key, it doesn't have an ordinal position in the array. From http://php.net/manual/en/language.types.array.php:
An array in PHP is actually an ordered map. A map is a type that associates values to keys. This type is optimized for several different uses; it can be treated as an array, list (vector), hash table (an implementation of a map), dictionary, collection, stack, queue, and probably more. As array values can be other arrays, trees and multidimensional arrays are also possible.
Ordered maps don't assign ordinal keys on top of the already existing string keys.
What you could do though, to get a psuedo-ordinal-key is increment a variable.
$i=0;
foreach( $array as $key => $value ) {
echo $i.':'.$key.':'.$value;
$i++;
}
Will echo out each ordinal key, key, and value in the array.
Have another variable that will increase in value after each iteration.
You can use the current function like so:
foreach($array as $value){
$array_key = search_array($value, $array);
echo current( $array );
echo $value;
}
Or you can just add a counter to your loop like so:
$count = 0;
foreach($array as $value){
$array_key = search_array($value, $array);
echo $count++;
echo $value;
}
<?php
$arry = array("id" => 2; "username" => "foobar");
$idx = 0;
foreach($array as $value){
if(array_search(arry, $value)) echo "element found: ".$idx;
$idx++;
}
?>
What you need is another variable - $idx in the above example to count the iterations, as you can't use the "key" corresponding to the value as they're named.
Also the search function is called array_search indeed.