I think this is a naive question, but I can't find the proper syntax.
I have this code:
for ($i=1; $i<count($MyArray1); $i++){
$element=$MyArray1[$i];
$foo = $AnotherArray[$element];
echo $foo;
}
How can I skip the second line? I mean, the third line to be something like
$foo = $AnotherArray[$MyArray1[$i]];
for ($i=1; $i<count($MyArray1); $i++){
echo $AnotherArray[$MyArray1[$i]];
}
You can skip a fair amount of that code to make it a bit clearer. Firstly use foreach instead of for as it's a much more reliable way of iterating over arrays. Secondly I've broken down what you're trying to do, to simplify how you're getting it. Basically using the values of one array as the keys of another. So how to do it in three lines:
foreach(array_intersect_key($AnotherArray, array_flip($MyArray1)) as $value) {
echo $value;
}
This is using the excellent array_intersect_key method to grab all of the values from $AnotherArray with keys that match in the other array. As you want to use the values, we use array_flip to swap the keys and values, then just loop over the result and echo it.
Related
I am tring to do (like) a 2 dimensional array, case insensitive.
I have:
foreach ($rows as $key=>$row) {
$names[$key]=$row['Name'];
}
array_multisort($rows,SORT_STRING|SORT_FLAG_CASE,$names);
The above ends up producing the same result (with or without case flag).
Sick of staring at this, any ideas from somebody outside?
First of all SORT_FLAG_CASE is only available in PHP v5.4+ so I suggest checking which version of PHP you are running (maybe 'uksort' could help if 5.3ish).
If not, make sure all the values that you put into $names lowercase or uppercase.
You have the order of the arguements $rows and $names reversed in the call to array_multisort.
Lastly if it comes from a database (or some other manner that means you cant change the data on the way into the array) then you can use array_walk.
Hope that helps
Since I ran into this with PHP 5.3.16, I thought I'd share my simple solution: just convert your keys to lower (or upper) case, e.g.:
foreach ($rows as $key=>$row) {
$names[$key]=strtolower($row['Name']);
}
array_multisort($names,SORT_STRING,$rows);
I also swapped the $rows & $names and removed the SORT_FLAG_CASE (to get rid of the log message).
You can also do a sort within a sort, so you can use usort with strcasecmp:
foreach ($rows as $key=>$row) {
$names[$key]=row['Name'];
}
array_multisort(usort($names,strcasecmp),$rows);
Above answer didn't work, because the first array got mingled while the other one didn't. So I wrote a general multidimensional array case insensitive compare function. It also can use multiple keys:
function array_casecmp($keys) {
if (gettype($keys) != "array") $keys = func_get_args();
return function ($a, $b) use ($keys) {
foreach($keys as $value) {
$akeys = $akeys . $a[$value];
$bkeys = $bkeys . $b[$value];
}
return strcasecmp($akeys, $bkeys);
};
}
Use it like:
usort($files,strcasecmp(array(0,1)); // with standard array
usort($files,strcasecmp(1); // single key
usort($files,strcasecmp(0,1); // arguments are converted to array
usort($files,strcasecmp("dir","link")); // you can also use symbolic keys
usort($files,strcasecmp(0,1,2,3,4,...); // use as many keys as you like
Keep in mind that the keys are concatenated, so maybe you have to use str_pad in your array colums to keep them seperated in the right way.
In the PHP manual, (array_push) says..
If you use array_push() to add one element to the array it's better to
use $array[] = because in that way there is no overhead of calling a
function.
For example :
$arr = array();
array_push($arr, "stackoverflow");
print_r($arr);
vs
$arr[] = "stackoverflow";
print_r($arr);
I don't understand why there is a big difference.
When you call a function in PHP (such as array_push()), there are overheads to the call, as PHP has to look up the function reference, find its position in memory and execute whatever code it defines.
Using $arr[] = 'some value'; does not require a function call, and implements the addition straight into the data structure. Thus, when adding a lot of data it is a lot quicker and resource-efficient to use $arr[].
You can add more than 1 element in one shot to array using array_push,
e.g. array_push($array_name, $element1, $element2,...)
Where $element1, $element2,... are elements to be added to array.
But if you want to add only one element at one time, then other method (i.e. using $array_name[]) should be preferred.
The difference is in the line below to "because in that way there is no overhead of calling a function."
array_push() will raise a warning if the first argument is not
an array. This differs from the $var[] behaviour where a new array is
created.
You should always use $array[] if possible because as the box states there is no overhead for the function call. Thus it is a bit faster than the function call.
array_push — Push one or more elements onto the end of array
Take note of the words "one or more elements onto the end"
to do that using $arr[] you would have to get the max size of the array
explain:
1.the first one declare the variable in array.
2.the second array_push method is used to push the string in the array variable.
3.finally it will print the result.
4.the second method is directly store the string in the array.
5.the data is printed in the array values in using print_r method.
this two are same
both are the same, but array_push makes a loop in it's parameter which is an array and perform $array[]=$element
Thought I'd add to the discussion since I believe there exists a crucial difference between the two when working with indexed arrays that people should be aware of.
Say you are dynamically creating a multi-dimensional associative array by looping through some data sets.
$foo = []
foreach ($fooData as $fooKey => $fooValue) {
foreach ($fooValue ?? [] as $barKey => $barValue) {
// Approach 1: results in Error 500
array_push($foo[$fooKey], $barKey); // Error 500: Argument #1 ($array) must be of type array
// NOTE: ($foo[$fooKey] ?? []) argument won't work since only variables can be passed by reference
// Approach 2: fix problem by instantiating array beforehand if it didn't exist
$foo[$fooKey] ??= [];
array_push($foo[$fooKey], $barKey);
// Approach 3: One liner approach
$foo[$fooKey][] = $barKey; // Instantiates array if it doesn't exist
}
}
Without having $foo[$fooKey] instantiated as an array beforehand, we won't be able to do array_push without getting the Error 500. The shorthand $foo[$fooKey][] does the heavy work for us, checking if the provided element is an array, and if it isn't, it creates it and pushes the item in for us.
I know this is an old answer but it might be helpful for others to know that another difference between the two is that if you have to add more than 2/3 values per loop to an array it's faster to use:
for($i = 0; $i < 10; $i++){
array_push($arr, $i, $i*2, $i*3, $i*4, ...)
}
instead of:
for($i = 0; $i < 10; $i++){
$arr[] = $i;
$arr[] = $i*2;
$arr[] = $i*3;
$arr[] = $i*4;
...
}
edit- Forgot to close the bracket for the for conditional
No one said, but array_push only pushes a element to the END OF THE ARRAY, where $array[index] can insert a value at any given index. Big difference.
I got a 2d-array containing a "column" on which this whole array is to be sorted. As I learned here, it is quite straightforward using array_multisort. My problem is, that this to be sorted over column contains values that needs to be compared in an unusual way. So I thought of something like this:
function main(){
$toBeSorted = array(array(...), ..., array(...));
$sortColumnIndex = n;
$sort_column = array();
//Code copied from provided link
foreach ($toBeSorted as $row)
$sort_column []= $row[$sortColumnIndex];
array_multisort($this->comparator(),$sort_column, $toBeSorted);
}
function comparator(a,b){
return 1;
}
As you can see, I want to pass my comparator to that sort-function. I probably think to much in a non-php way.
There is the usort function, which sorts by using a callback.
Otherwise you could have a look at the array_walk and array_walk_recursive functions, which iterate over an array and apply a function to every member.
I solved it by transforming my sorting space in one, that array_multisort can handle:
...
$sortColumn = array();
foreach($toBeSorted as $value){
$sortColumn[] = $this->transform($value);
}
array_multisort($sortColumn, $toBeSorted);
...
my transformation function simply does everything I imagined the callback would do.
function transform($value){
//i.e. return real part of complex number
//or parse strings or any kind of strange datatypes
}
I'd like to make an associative array in PHP where the key is a pair of strings.
At first I was considering concatenating the strings with some sort of unique divider in the middle, and then separating them later, but this seems like a hacky workaround for using a pair.
Consider the following code:
$andrew = array('Andrew', 'Rasmussen');
$john = array('John', 'Smith');
$container[$andrew] = 15;
$container[$john] = 12;
$pair = array('Andrew', 'Rasmussen');
if (array_key_exists($pair, $container)) {
echo 'true';
} else {
echo 'false';
}
Obviously this code will not work because you can't use an array as a key in an array in PHP. Is there a good way to do something like this without concatenating and then later parsing the strings?
Edit
I have a reason for wanting to do this. I have an array(key=string1,value=array(key=string2,value=occurrences)) and I'm trying to find the top 5 (in terms of occurrences) of string pairs. So I'm basically trying to flatten this into a 1d array and then sort it so I can easily grab the top 5. But to do this I'll need to be able to extract the strings out separately after I've sorted, which can be done with the divider algorithm explained above, but this is not preferable, which is why I'm asking for an alternative.
How about serializeing the key?
$pair = array('Andrew', 'Rasmussen');
if (array_key_exists( serialize( $pair), $container)) {
echo 'true';
} else {
echo 'false';
}
You can make use of multidimensional arrays (by using it as $container["Andrew"]["Rasmussen"] for example).
Also, you can encapsulate all the "hacking" (be it two-dimensional arrays or string concatenation) in your custom ArrayIndexedByPairs class, which could be like the following:
interface IArrayIndexedByPairs {
public Add($key1, $key2, $value);
public Contains($key1, $key2);
public Get($key1, $key2);
}
I'm using a nestedsortable jQuery plugin that gives me the order/sort of the elements serialized.
And example of this serialitzation (root means parent_id=0):
id[1]=root&id[5]=1&id[2]=1&id[3]=1&id[4]=3
First thing I'll do is explode by &:
$serialized = "id[1]=root&id[5]=1&id[2]=1&id[3]=1&id[4]=3";
$exploded = explode("&", $serialized);
But I don't know then how to manage a id[1]=root or id[3]=1. How I can do it?
And another question. In this way I don't know which is how to store the order. When I've the exploded with in array like array("id"=>1, "parent"=>"root"); I've to store the order. I will do it with an index, but how I recognise nested levels?
An example:
$i = 0;
foreach($exploded as $explode)
{
//update every id in MySQL and set parent=$explode["parent"] and order=$i
$i++;
}
But if I've N levels, how I can have a index $i for every one of them?
Thank you in advance!
Rather than exploding, you could try parse_str()
<?php
parse_str("id[1]=root&id[5]=1&id[2]=1&id[3]=1&id[4]=3",$result);
print_r($result);
?>
From there you can work with the array.