Independent Nested Loops in PHP - php

Say i have two different arrays. I want to get each value from the first array, and add to it some values of each key in the second array. How do i do this please?
I tried using a foreach loop inside a foreach loop and for each value in the first array, it appends each value of the second array which isn't what i want
$array1 = array(chris, kate, john, jane);
$array2 = array('first' => 1, 'second' => 2, 'third' => 3, 'fourth' => 4);
foreach($array1 as $name){
foreach($array2 as $k => $v){
echo $name . "-" . $v;
}
}
I want my output to look like this
chris-1
kate-2
john-3
jane-4
Sometimes, the count of both array aren't the same. Some values in the first array produces an empty string, so in cases like that, it should just skip the value. Once the empty string in array1 is skipped or deleted, the count then matches array2
My above nested loop can't give me this. How do i go about this please?

Firstly I would use array_filter() to remove the empty strings from $array1:
$array1 = array(chris, kate, john, jane);
$array1 = array_filter($array1, function($value) {
return $value !== '';
});
Now we need to reindex the array to account for the gaps we made when removing empty strings.
$array1 = array_values($array1);
Considering you don't use the 'first', 'second', etc keys in $array2 for anything, we can just get rid of them using array_values(). This will leave us with an array like array(1,2,3,4) which will make accessing the data later on a little easier.
$array2 = array('first' => 1, 'second' => 2, 'third' => 3, 'fourth' => 4);
$array2 = array_values($array2);
Now we can loop through the first array and access the same position in the second array to create the final string.
// Assign the current element's numeric position to the $i variable on each iteration.
foreach($array1 as $i => $name){
echo $name . "-" . $array2[$i];
}
Final Code
$array1 = ['chris', 'kate', '', 'john', 'jane'];
$array1 = array_filter($array1, function ($value) {
return $value !== '';
});
$array1 = array_values($array1);
$array2 = ['first' => 1, 'second' => 2, 'third' => 3, 'fourth' => 4];
$array2 = array_values($array2);
foreach ($array1 as $i => $name) {
echo $name . "-" . $array2[$i];
}

Related

If value of first array is found on second array, replace and echo it

I have 2 arrays:
$array1 = array('first', 'second', 'third', 'fourth');
$array2 = array('second' => 'bye', 'first' => 'hello', 'third' => 'see you', 'fifth' => 'good evening');
and I echo the content of $array1 like
foreach ($array1 as $extra) {
echo $extra; }
What I am trying to do is to check every time before echoing the $extra whether the output is found in $array2. And if yes, to echo the value of the array2 instead.
So in my example above, instead of first second third fourth I want to echo hello bye see you fourth.
How can I do this?
You can do
$array1 = array('first', 'second', 'third', 'fourth');
$array2 = array('second' => 'bye', 'first' => 'hello', 'third' => 'see you', 'fifth' => 'good evening');
print_r(array_intersect_key( $array2 ,array_flip($array1)));
Output
Array
(
[second] => bye
[first] => hello
[third] => see you
)
Sandbox
array_intersect_key() returns an array containing all the entries of array1 which have keys that are present in all the arguments.
https://www.php.net/manual/en/function.array-intersect-key.php
And
array_flip() returns an array in flip order, i.e. keys from array become values and values from array become keys.
https://www.php.net/manual/en/function.array-flip.php
Update
I know but it's array1 that is the "string". Array2 is the replacements. See the question: I want to echo hello bye see you fourth
$array1 = array('first', 'second', 'third', 'fourth');
$array2 = array('second' => 'bye', 'first' => 'hello', 'third' => 'see you', 'fifth' => 'good evening');
echo implode(' ', array_intersect_key( array_merge(array_combine($array1,$array1), $array2) ,array_flip($array1)));
Output
hello bye see you fourth
Sandbox
The difference with this one is this bit
$array2 = array_merge(array_combine($array1,$array1), $array2)
What this does is make a new array with array_combine which has the same keys as values. In this case:
array('first'=>'first', 'second'=>'second', 'third'=>'third', 'fourth'=>'fourth')
Then we use the fact that when merging 2 rows the second array will overwrite keys from the first so we merge that with our original $array2
$array2 = array('second' => 'bye', 'first' => 'hello', 'third' => 'see you', 'fourth'=>'fourth', 'fifth' => 'good evening');
So by doing this "extra" step we insure that all elements in $array1 exist in $array2 - the order of $array1 is also preserved - in this case it just adds 'fourth'=>'fourth' but that is exactly what we need for the intersect to work.
Then we just implode it.
UPDATE2
This is a simpler one using preg_filter and preg_replace
$array1 = array('first', 'second', 'third', 'fourth');
$array2 = array('second' => 'bye', 'first' => 'hello', 'third' => 'see you', 'fifth' => 'good evening');
echo implode(' ',preg_replace(preg_filter('/(.+)/', '/(\1)/i', array_keys($array2)), $array2, $array1));
Output
hello bye see you fourth
It's very similar to the str_replace one, so I didn't want to post it as it's own answer. But it does have a few benefits over str_replace. For example
echo implode(' ',preg_replace(preg_filter('/(.+)/', '/\b(\1)\b/i', array_keys($array2)), $array2, $array1));
Now we have \b word boundaries, which means first wont match firstone etc.
Sorry I really enjoy doing things like this, it's "fun" for me.
You can access $array2[$key] and use the null-coalescing operator since you apparently want to fall back to the value from $array1 if it doesn't exist as a key in $array2.
foreach ($array1 as $key) {
echo $array2[$key] ?? $key, ' ';
// [PHP5] echo isset($array2[$key]) ? $array2[$key] : $key, ' ';
}
Demo: https://3v4l.org/3vQYt
Note: this adds a potentially unwanted space at the end. If that's the case, either add a condition to the loop or do something like this instead:
echo implode(' ', array_map(function ($key) use ($array2) {
return $array2[$key] ?? $key;
// [PHP5] return isset($array2[$key]) ? $array2[$key] : $key;
}, $array1));
Demo: https://3v4l.org/VCDVt
foreach ($array1 as $extra) {
foreach ($array2 as $key=>$value) {
if($extra==$key){
echo $value;
}
}
}
something like this
Just use isset:
foreach($array1 as $e) {
$val = isset($array2[$e]) ? $array2[$e] : $e;
echo $val;
}
Doc can be found here: https://www.php.net/manual/en/function.isset.php
You can just implode the first array then use str_replace to replace the words from the second in the imploded string.
No need for loops in my opinion.
echo str_replace(array_keys($array2), $array2, implode(" ", $array1));
//hello bye see you fourth
Array_keys will take the keys from array2 and make them the find, then the values from array2 will be the replacements.
https://3v4l.org/UIWV0

How can i convert ARRAY into VARIABLE? [duplicate]

I have an array as the following:
function example() {
/* some stuff here that pushes items with
dynamically created key strings into an array */
return array( // now lets pretend it returns the created array
'firstStringName' => $whatEver,
'secondStringName' => $somethingElse
);
}
$arr = example();
// now I know that $arr contains $arr['firstStringName'];
I need to find out the index of $arr['firstStringName'] so that I am able to loop through array_keys($arr) and return the key string 'firstStringName' by its index. How can I do that?
If you have a value and want to find the key, use array_search() like this:
$arr = array ('first' => 'a', 'second' => 'b', );
$key = array_search ('a', $arr);
$key will now contain the key for value 'a' (that is, 'first').
key($arr);
will return the key value for the current array element
http://uk.php.net/manual/en/function.key.php
If i understand correctly, can't you simply use:
foreach($arr as $key=>$value)
{
echo $key;
}
See PHP manual
If the name's dynamic, then you must have something like
$arr[$key]
which'd mean that $key contains the value of the key.
You can use array_keys() to get ALL the keys of an array, e.g.
$arr = array('a' => 'b', 'c' => 'd')
$x = array_keys($arr);
would give you
$x = array(0 => 'a', 1 => 'c');
Here is another option
$array = [1=>'one', 2=>'two', 3=>'there'];
$array = array_flip($array);
echo $array['one'];
Yes you can infact php is one of the few languages who provide such support..
foreach($arr as $key=>$value)
{
}
if you need to return an array elements with same value, use array_keys() function
$array = array('red' => 1, 'blue' => 1, 'green' => 2);
print_r(array_keys($array, 1));
use array_keys() to get an array of all the unique keys.
Note that an array with named keys like your $arr can also be accessed with numeric indexes, like $arr[0].
http://php.net/manual/en/function.array-keys.php
you can use key function of php to get the key name:
<?php
$array = array(
'fruit1' => 'apple',
'fruit2' => 'orange',
'fruit3' => 'grape',
'fruit4' => 'apple',
'fruit5' => 'apple');
// this cycle echoes all associative array
// key where value equals "apple"
while ($fruit_name = current($array)) {
if ($fruit_name == 'apple') {
echo key($array).'<br />';
}
next($array);
}
?>
like here : PHP:key - Manual

Select 2 random elements from associative array

So I have an associative array and I want to return 2 random values from it.
This code only returns 1 array value, which is any of the 4 numbers at random.
$array = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4);
$key = array_rand($array); //array_rand($array,2); Putting 2 returns Illegal offset type
$value = $array[$key];
print_r($value); //prints a single random value (ex. 3)
How can I return 2 comma separated values from the array values only? Something like 3,4?
array_rand takes an additional optional parameter which specifies how many random entries you want out of the array.
$input_array = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4);
$rand_keys = array_rand($input_array, 2);
echo $input_array[$rand_keys[0]] . ',' . $input_array[$rand_keys[1]];
Check the PHP documentation for array_rand here.
Grab the keys from the array with array_keys(), shuffle the keys with shuffle(), and print out the values corresponding to the first two keys in the shuffled keys array, like so:
$array = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4);
$keys = array_keys( $array);
shuffle( $keys);
echo $array[ $keys[0] ] . ',' . $array[ $keys[1] ];
Demo
Or, you can use array_rand()'s second parameter to grab two keys, like so:
$array = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4);
$keys = array_rand( $array, 2);
echo $array[ $keys[0] ] . ',' . $array[ $keys[1] ];
Demo
There is a more efficient approach that preserves keys and values.
function shuffle_assoc(&$array) {
$keys = array_keys($array);
shuffle($keys);
foreach($keys as $key) {
$new[$key] = $array[$key];
}
$array = $new;
return true;
}
Check the documentation here
$a=rand(0,sizeof($array));
$b=$a;
while ($a==$b) $b=rand(0,sizeof($array));
$ar=array_values($array);
$element1=$ar[$a];
$element2=$ar[$b];
Should be more efficient than shuffle() and freinds, if the array is large.

php. array_values function. how to get mapping from old keys to new keys?

There is function array_values in PHP such that
$array2 = array_values($array1);
$array2 has the same values as $array1 but keys are from
0 to sizeof($array1) - 1. Is it possible to get mapping from old keys to new keys?
EDIT. I will explain on an example:
$array1 = array( 'a' => 'val1', 'b' => 'val1');
$array2 = array_values( $array1 );
so now array2 has next values
$array2[0] = 'val1'
$array2[1] = 'val2'
How get array3 such that:
$array3['a'] = 0
$array3['b'] = 1
To produce a key map you need to first get the keys into a regular array and then flip the keys and values:
$array1_keymap = array_flip(array_keys($array1));
For example:
$array1 = array(
'a' => 123,
'b' => 567,
);
$array1_values = array_values($array1);
$array1_keymap = array_flip(array_keys($array1));
Value of $array1_values:
array(
0 => 123,
1 => 567,
);
Value of $array1_keymap:
array(
'a' => 0,
'b' => 1,
);
So:
$array1['a'] == $array1_values[$array1_keymap['a']];
$array1['b'] == $array1_values[$array1_keymap['b']];
Yes, as simple as
$array2 = $array1;
In this case you would get both values and keys like they are in the original array.
$keyMapping = array_combine(array_keys($array1), array_keys($array2));
This the keys of $array1 and maps them to the keys of $array2 like so
<?php
$array1 = array(
'a' => '1',
'b' => '2',
);
$array2 = array_values($array1);
print_r(array_combine(array_keys($array1), array_keys($array2)));
Array
(
[a] => 0
[b] => 1
)
You can use:
$array3 = array_keys($array1);
Now $array3[$n] is the key of the value in $array2[$n] for any 0 <= $n < count($array1). You can use this to determine which keys were in which places.
If you want to keep the same value of array1 but change the key to index numbers, try this:
$array2 = array();
foreach ($array1 as $key => $value){
$array2[] = $value;
// or array_push($array2, $value);
}
var_dump($array2);

PHP subtract array values

I have an array with keys and values. Each value is an integer. I have an other array with the same keys. How can I subtract all of the values for the matching keys? Also there might be keys that do not occur in the second array but both arrays have the same length. If there is a key in array 2 that is not present in array 1 its value should be unchanged. If there is a key in the first array that is not in the second it should be thrown away. How do I do it? Is there any built-in function for this?
If I would write a script it would be some kind of for loop like this:
$arr1 = array('a' => 1, 'b' => 3, 'c' => 10);
$arr2 = array('a' => 2, 'b' => 1, 'c' => 5);
$ret = array();
foreach ($arr1 as $key => $value) {
$ret[$key] = $arr2[$key] - $arr1[$key];
}
print_r($ret);
/*
should be: array('a' => 1, 'b' => -2, 'c' => -5)
*/
I did not add the occasion here a key is in one array and not in the other.
You could avoid the foreach using array functions if you were so inclined.
The closure provided to array_mapdocs below will subtract each $arr1 value from each corresponding $arr2. Unfortunately array_map won't preserve your keys when using more than one input array, so we use array_combinedocs to merge the subtracted results back into an array with the original keys:
$arr1 = array('a' => 1, 'b' => 3, 'c' => 10);
$arr2 = array('a' => 2, 'b' => 1, 'c' => 5);
$subtracted = array_map(function ($x, $y) { return $y-$x; } , $arr1, $arr2);
$result = array_combine(array_keys($arr1), $subtracted);
var_dump($result);
UPDATE
I was interested in how the array functions approach compared to a simple foreach, so I benchmarked both using Xdebug. Here's the test code:
$arr1 = array('a' => 1, 'b' => 3, 'c' => 10);
$arr2 = array('a' => 2, 'b' => 1, 'c' => 5);
function arrayFunc($arr1, $arr2) {
$subtracted = array_map(function ($x, $y) { return $y-$x; } , $arr1, $arr2);
$result = array_combine(array_keys($arr1), $subtracted);
}
function foreachFunc($arr1, $arr2) {
$ret = array();
foreach ($arr1 as $key => $value) {
$ret[$key] = $arr2[$key] - $arr1[$key];
}
}
for ($i=0;$i<10000;$i++) { arrayFunc($arr1, $arr2); }
for ($i=0;$i<10000;$i++) { foreachFunc($arr1, $arr2); }
As it turns out, using the foreach loop is an order of magnitude faster than accomplishing the same task using array functions. As you can see from the below KCachegrind callee image, the array function method required nearly 80% of the processing time in the above code, while the foreach function required less than 5%.
The lesson here: sometimes the more semantic array functions (surprisingly?) can be inferior performance-wise to a good old fashioned loop in PHP. Of course, you should always choose the option that is more readable/semantic; micro-optimizations like this aren't justified if they make the code more difficult to understand six months down the road.
foreach ($arr2 as $key => $value) {
if(array_key_exists($key, $arr1) && array_key_exists($key, $arr2))
$ret[$key] = $arr2[$key] - $arr1[$key];
}
PHP does not offer vectorized mathematical operations. I would stick with your current approach of using a loop.
First, I would get the set of array keys for each array. (See the array_keys function). Then, intersect them. Now you will have the keys common to each array. (Take a look at the array_intersect function). Finally, iterate. It's a readable and simple approach.
Lastly, you could take a look at a library, such as Math_Vector: http://pear.php.net/package/Math_Vector

Categories