elegant way to map two arrays to each other - php

I've got two arrays, one with IDs and one with Names:
$ids = array(4, 13, 6, 8, 10);
$names = array('alice', 'bob', 'charles', 'david', 'elizabeth');
I need to update the db so that the rows with the ids have the names in the array. Here's the tricky bit: I also have two ints:
$special_name = 2; // the index in $names, in this case we mean 'charles'
$special_id = 13; // the id value
I don't care about which name goes to which id, except that the name with the $special_name should go on the $special_id.
What's the most elegant way to get there? All of the methods that I'm thinking of seem pretty messy. The best I've thought of is to extract out the special items from each array, and do those first, and then do the rest, perhaps building a new array like this:
$mapped = new array();
$mapped[$special_id] = $names[$special_name];
foreach ($ids as $id) {
if ($id != $special_id) {
$mapped[$id] = current($names);
}
// advance $names pointer
$next_name = next($names);
if ($next_name == $special_name) next($names);
}
I haven't tested that yet (I'm about to) but it's meant to produce something like:
$mapped = array(13=>'charles', 4=>'alice',6=>'bob', 8=>'david', 10=>'elizabeth');
and then running through that to do the actual update. Got a better idea?
UPDATE: added the possible solution above. Meanwhile a couple answers have come in.

If it wasn't for the special Ids, you could have just array_combine'd the two arrays. Here is how I think to have solved the issue:
Setup
$ids = array(4, 13, 6, 8, 10);
$names = array('alice', 'bob', 'charles', 'david', 'elizabeth');
$specialNameIndex = 2;
$specialId = 13;
Solution
$result = array($specialId => $names[$specialNameIndex]);
unset($ids[array_search($specialId, $ids)],
$names[$specialNameIndex]);
$result += array_combine($ids, $names);
Result
print_r($result);
Array
(
[13] => charles
[4] => alice
[6] => bob
[8] => david
[10] => elizabeth
)

you can use array_combine and then set/append your special values:
$mapped = array_combine($ids, $names);
$mapped[$special_id] = $names[$special_name];

Are the $ids and $names arrays synced? (Does 4 correspond to 'alice'?)
for ($i=0; $i < count($ids); $i++) {
$indexed[$ids[$i]] = $names[$i]; // $indexed[4] = 'alice';
$indexed2[] = array ( $ids[$i] => $names[$i] ); // $indexed[0] = ( 4 => 'alice')
}
Pick your fave

Since you use the default indexes you can use foreach() on keys($ids) to get the indexes so that you can iterate through both arrays at once. Just compare the value of the current index of $ids and use the alternate index of $names when appropriate.

Related

How to return value of an array inside a loop and use it outside in PHP

I have a code like this:
Lets assume that this arrays has this values:
$arr1 = array();
$arr2 = array();
$result = array();
$arr1[] = array( 'grade' => [1,2,3,4] );
$arr2[] = array( 'grade' => [1,2,3,4] );
foreach($arr1 as $a1){
$set1 = $a1['grade'];
foreach($arr2 as $a2){
$set2 = $a2['grade'];
}
$result[] = array('show_result' => $set1+$set2);
}
foreach{$result as $res){
echo $res['show_result'];
}
The output of the array $res['show_result'] must be:
2, 4, 6, 8
But I get the wrong addition of this arrays. Help will be much appreciated.
As Joni said, your first error is on line 3: ' should be ;
Then, you're not filling arrays like you wanted : array( 'grade' => 1,2,3,4 ); creates an array with first key is 'grade' with value '1', then second key is '0' with value '2' etc...
Your last foreach loop has a syntax error similar to your first error.
See a working correction here
$arr1 = array();
$arr2 = array();
$result = array();
array_push($arr1, 1, 2, 3, 4); //fill array with 4 values (integers)
array_push($arr2, 1, 2, 3, 4); //fill array with 4 values (integers)
//so $arr1 & $arr2 are now a 4 elements arrays
$length = count($arr1); //size of array, here 4
for ($i = 0; $i < $length; $i++) { //loop over arrays
array_push($result, ($arr1[$i] + $arr2[$i])); //fill the results array with sum of the values from the same position
}
var_dump($result);
You have quite a few syntax errors in your code.
Although this solution works, the idea behind using the same counter, $i, to extract a value from both arrays is brittle. For example, you'll get an Undefined offset if the first array has 5 grades instead of 4. If you take a step back and explain your problem in the larger context, perhaps we can provide a better solution. I get the sneaking suspicion you're asking an XY Problem.
http://sandbox.onlinephpfunctions.com/code/bb4f492c183fcde1cf4edd50de7ceebf19fe343a
<?php
$gradeList1 = ['grade' => [1,2,3,4]];
$gradeList2 = ['grade' => [1,2,3,4]];
$result = [];
for ($i = 0; $i < count($gradeList1['grade']); $i++) {
$first = $gradeList1['grade'][$i];
$second = $gradeList2['grade'][$i];
$result['show_result'][] = (int)$first + (int)$second;
}
var_dump($result);

PHP find max between variables

I'm trying to find out wich variable is bigger (those are all integers):
<?php
$ectoA=3;
$ectoB=5;
$mesoA=0;
$mesoB=4;
$endoA=11;
$endoB=11;
echo max($ectoA,$ectoB,$mesoA,$mesoB,$endoA,$endoB);
I tried with max but it gives the value and not the $varName.
I want to get the name of the variable and if there are two that are equal I need both.
Thanks for the help.
As suggested i tried this and worked but still got to know if I have two MAX values I need to do something else...
$confronto = [
'ectoA' => $ectoA,
'ectoB' => $ectoB,
'endoA' => $endoA,
'endoB' => $endoB,
'mesoA' => $mesoA,
'mesoB' => $mesoB,
];
$result= array_keys($confronto,max($confronto));
$neurotipo = $result[0];
echo $neurotipo;
I want endoA and endoB to be identified...
You can define an array instead, or compact your variables into an array:
//$array = array('ectoA'=>3,'ectoB'=>5,'mesoA'=>0,'mesoB'=>4,'endoA'=>11,'endoB'=>11);
$array = compact('ectoA','ectoB','mesoA','mesoB','endoA','endoB');
$result = array_keys($array, max($array));
Then compute the max() of that array and use array_keys() to search for the max number and return the keys.
print_r($result);
Yields:
Array
(
[0] => endoA
[1] => endoB
)
I would definitely recommend using an array. Then you can do something like this:
$my_array = array(3, 5, 0, 4, 11, 11);
$maxIndex = 0;
for($i = 1; $i < count($my_array); $i++) {
if($my_array[$i] > $my_array[$maxIndex])
$maxIndex = $i;
}
Another option with array keys would be:
$my_array = array("ectoA" => 3, "ectoB" => 5, "mesoA" => 0, "mesoB" => 4, "endoA" => 11, "endoB" => 11);
$maxIndex = "ectoA";
while($c = current($my_array)) {
$key = key($my_array);
if($my_array[$key] > $my_array[$maxIndex])
$maxIndex = $key;
next($my_array);
}
Note: Code not tested, but should be the gist of what needs to be done
use the array like this
<?php
$value= array (
"ectoA" =>3,
"ectoB"=>5,
"mesoA"=>0,
"mesoB"=>4,
"endoA"=>11,
"endoB"=>11);
$result= array_keys($value,max($values))
print_r($result);
?>
As per the documentation, Since the two values are equal, the order they are provided determines the result $endoA is the biggest here.
But I am not sure your intention is to find the biggest value or which variable is the highest
Your code seems to be a working one.
But it would print for you the value of the maximum number, not the name of the variable.
To have the name of the variable at the end you should add some additional code like:
$max = (max($ectoA,$ectoB,$mesoA,$mesoB,$endoA,$endoB);
if($max == $ectoA) echo "ectoA";
if($max == $ectoB) echo "ectoB";
// ... same goes for other variables
But working with an array would be the most proper solution.

Cleanest way of working out next variable name based on sequential order?

Hope my title explains it ok! Here's more detail:
I'm creating an array which stores keys & their values. Eg.
test1 = hello
test2 = world
test3 = foo
What is the cleanest way of working out what to call the next key? Let's say I will know the first part is 'test', but I don't know what the highest value number is. Obviously in this case I want it to be called 'test4'.
In the example below I want the next key to be 'test46', as it is the next highest value:
test6 = blah
test45 = boo
test23 = far
This sounds like you should be using an array with numerical indexes instead.
You could however use some code like this...
$arr = array('test6', 'test45', 'test23');
$max = 0;
foreach($arr as $value) {
$number = filter_var($value, FILTER_SANITIZE_NUMBER_INT);
$max = max($max, $number);
}
$newKey = 'test' . ++$max; // string(6) "test46"
CodePad.
Implementation of #alex answer without using a loop:
$arr = array('test6', 'test45', 'test23');
$max = max(filter_var_array($arr, FILTER_SANITIZE_NUMBER_INT));
$newKey = 'test' . ++$max; // string(6) "test46"
CodePad
This data structure would be better stored as an array.
$test = array();
$test[] = 'hello';
$test[] = 'world';
$test[] = 'foo';
You then don't need to know the highest number to add a new item, just use the empty brackets syntax (shown above) to add an item to the end of the array.
You then have access to a wealth of array functions that PHP gives you to work with your data: http://php.net/manual/en/ref.array.php
When you want to get item 43 from the array, use:
echo $test[42];
Arrays are counted from 0 rather than 1, so item 43 will have an index of 42.
What are you using that for? If numbering the array is a must-have, just use a simple numerical indexed array instead, and simply prepend the key with "test" if you need it to show up as "test1":
<?php
$array = array(
6 => 'blah',
45 => 'boo',
23 => 'bar'
);
$array[] = 'new';
echo $array[46] . "\n"; // this is 'new'
foreach( $array as $key => $value ) {
echo "test$key = $value<br />\n"; // test6 = blah
}

Replace non-specified array values with 0

I want to replace all array values with 0 except work and home.
Input:
$array = ['work', 'homework', 'home', 'sky', 'door']
My coding attempt:
$a = str_replace("work", "0", $array);
Expected output:
['work', 0, 'home', 0, 0]
Also my input data is coming from a user submission and the amount of array elements may be very large.
A bit more elegant and shorter solution.
$aArray = array('work','home','sky','door');
foreach($aArray as &$sValue)
{
if ( $sValue!='work' && $sValue!='home' ) $sValue=0;
}
The & operator is a pointer to the particular original string in the array. (instead of a copy of that string)
You can that way assign a new value to the string in the array. The only thing you may not do is anything that may disturb the order in the array, like unset() or key manipulation.
The resulting array of the example above will be
$aArray = array('work','home', 0, 0)
A loop will perform a series of actions many times. So, for each element in your array, you would check if it is equal to the one you want to change and if it is, change it. Also be sure to put quote marks around your strings
//Setup the array of string
$asting = array('work','home','sky','door')
/**
Loop over the array of strings with a counter $i,
Continue doing this until it hits the last element in the array
which will be at count($asting)
*/
for($i = 0; $i < count($asting);$i++){
//Check if the value at the 'ith' element in the array is the one you want to change
//if it is, set the ith element to 0
if ($asting[$i] == 'work' || $asting[$i] == 'home')
$asting[$i] = 0;
}
Here is some suggested reading:
http://www.php.net/manual/en/language.types.array.php
http://www.php.net/manual/en/language.control-structures.php
But if you are struggling on stuff such as looping, you may want to read some introductory programming material. Which should help you really understand what's going on.
A bit other and much quicker way, but true, need a loop:
//Setup the array of string
$asting = array('bar', 'market', 'work', 'home', 'sky', 'door');
//Setup the array of replacings
$replace = array('home', 'work');
//Loop them through str_replace() replacing with 0 or any other value...
foreach ($replace as $val) $asting = str_replace($val, 0, $asting);
//See what results brings:
print_r ($asting);
Will output:
Array
(
[0] => bar
[1] => market
[2] => 0
[3] => 0
[4] => sky
[5] => door
)
An alternative using array_map:
$original = array('work','home','sky','door');
$mapped = array_map(function($i){
$exclude = array('work','home');
return in_array($i, $exclude) ? 0 : $i;
}, $original);
you may try array_walk function:
function zeros(&$value)
{
if ($value != 'home' && $value != 'work'){$value = 0;}
}
$asting = array('work','home','sky','door','march');
array_walk($asting, 'zeros');
print_r($asting);
You can also give array as a parameter 1 and 2 on str_replace...
Just a small point to the for loop. Many dont realize the second comparing task is done every new iteration. So if it was a case of big array or calculation you could optimize loop a bit by doing:
for ($i = 0, $c = count($asting); $i < $c; $i++) {...}
You may also want to see http://php.net/manual/en/function.array-replace.php for original problem unless the code really is final :)
Try This
$your_array = array('work','home','sky','door');
$rep = array('home', 'work');
foreach($rep as $key=>$val){
$key = array_search($val, $your_array);
$your_array[$key] = 0;
}
print_r($your_array);
There are a few techniques on this page that make zero iterated function calls -- which is good performance-wise. For best maintainability, I recommend separating your list of targeted string as a lookup array. By modifying the original array values by reference, you can swiftly replace whole strings and null coalesce non-targeted values to 0.
Code: (Demo)
$array = ['work', 'homework', 'home', 'sky', 'door'];
$keep = ['work', 'home'];
$lookup = array_combine($keep, $keep);
foreach ($array as &$v) {
$v = $lookup[$v] ?? 0;
}
var_export($array);
Output:
array (
0 => 'work',
1 => 0,
2 => 'home',
3 => 0,
4 => 0,
)
You can very easily, cleanly extend your list of targeted strings by merely extending $keep.
If you don't want a classic loop, you can use the same technique without modifying the original array. (Demo)
var_export(
array_map(fn($v) => $lookup[$v] ?? 0, $array)
);
this my final code
//Setup the array of string
$asting = array('work','home','sky','door','march');
/**
Loop over the array of strings with a counter $i,
Continue doing this until it hits the last element in the array
which will be at count($asting)
*/
for($i = 0; $i < count($asting); $i++) {
//Check if the value at the 'ith' element in the array is the one you want to change
//if it is, set the ith element to 0
if ($asting[$i] == 'work') {
$asting[$i] = 20;
} elseif($asting[$i] == 'home'){
$asting[$i] = 30;
}else{
$asting[$i] = 0;
}
echo $asting[$i]."<br><br>";
$total += $asting[$i];
}
echo $total;

Change values in first key from 0 to count(array) - 1

Ok, I have an array like so:
$myArray[32]['value'] = 'value1';
$myArray[32]['type'] = 'type1';
$myArray[33]['value'] = 'value2';
$myArray[33]['type'] = 'type2';
$myArray[35]['value'] = 'value3';
$myArray[42]['value'] = 'value4';
$myArray[42]['type'] = 'type4';
Ok, looking for a quick way to change all numbers in the first key 32, 33, 35, and 42 into 0, 1, 2, and 3 instead. But I need to preserve the 2nd key and all of the values. The array is already ordered correctly, since I ordered it using a ksort, but now I need to reset the array from 0 - count($myArray) - 1 and keep the 2nd key intact and its value as well.
Can someone please help me?
$myArray = array_values($myArray);
There might be simpler solutions but here is one working solution:
$myArray = array();
$myArray[32]['value'] = 'value1';
$myArray[32]['type'] = 'type1';
$myArray[33]['value'] = 'value2';
$myArray[33]['type'] = 'type2';
$myArray[35]['value'] = 'value3';
$myArray[42]['value'] = 'value4';
$myArray[42]['type'] = 'type4';
$map = array_flip(array_keys($myArray)); // map old keys to new keys.
$newarray = array();
foreach($myArray as $key => $value) {
$newarray[$map[$key]] = $value; // use new key and old value.
}
You don't need it. Why not to just leave this array alone? Unnecessary moves would lead your code to a mess.

Categories