Error merging arrays in PHP - php

I have nested arrays and want to append the content of one array into another when the keys match. Here is my function but instead of appending it is replacing.
function MergeArrays($arr, $ins)
{
if(is_array($arr))
{
if(is_array($ins))
foreach($ins as $k=>$v)
{
if(isset($arr[$k])&&is_array($v)&&is_array($arr[$k]))
{
$arr[$k] = MergeArrays($arr[$k], $v);
}
else
{
// This is the new loop :)
// while (isset($arr[$k]))
// $k++;
// HERE IS WHERE I WANT TO APPEND INSTEAD OF ADD
$arr[$k] = $v;
}
}
}
else if(!is_array($arr)&&(strlen($arr)==0||$arr==0))
{
$arr=$ins;
}
return($arr);
}
Any recommendations?
Thanks

You can merge the entries by either adding the arrays together, or using array_merge to merge the arrays into a new one.
Any reason you're not using array_merge_recursive to solve this without custom code?

I'm not sure I'm reading the question properly, I'm a little confused as to what you're doing, but this might help:
As far as I can tell, you want to append to the value of $arr[k] with the value of $v. Therefore you want to concat these things together.
Therefore you want to use .= instead of = on the line below your comment.

Related

Seeking advice to optimize the following code chunk. (I need to avoid the IF ELSES)

I have a JSON file with around 30 sub sections. Each subsection will be different. I wanted to convert the data inside it into a format i wanted. The code works fine. But i feel its not optimized 100%.
Client1Insurance, Client2Insurance, ClientFInsurance, FamilyInsurance, Client1Pension, Client2Pension, ClientFPension, FamilyPension.
Above is an example of how this JSON would look like. All above are arrays which have sub arrays inside them. There are around 30 arrays like this.
foreach ($json as $item) {
if (strpos($crmMapKey, "Insurance")) {
$returnArray[] = $this->handleInsurance($item);
} elseif (strpos($crmMapKey, "Pension")) {
$returnArray[] = $this->handlePension($item);
} ... continues the comparison till the json ends
}
I need a way to avoid this long if else comparions which I am not proud of. Will someone be able to suggest a better way to do this?
Thanks.
If they are named the same as you show in your code, something containing Insurance will call handleInsurance, etc. then just get the term and use it in the method call:
preg_match('/Insurance|Pension/', $crmMapKey, $match);
$returnArray[] = $this->{'handle'.$match[0]}($item);
If not then you can use a lookup array:
$lookup = ['Insurance' => 'doSomething', 'Pension' => 'doAnotherThing'];
preg_match('/Insurance|Pension/', $crmMapKey, $match);
$returnArray[] = $this->{'handle'.$lookup[$match[0]]}($item);
Or use the keys in the pattern so you only have to modify the array:
preg_match('/'.implode('|', array_keys($lookup)).'/', $crmMapKey, $match);
The switch I mentioned in a comment might not be the best but works:
switch(true) {
case strpos($crmMapKey, "Insurance") !== false;
$returnArray[] = $this->handleInsurance($item);
break;
case strpos($crmMapKey, "Pension") !== false;
$returnArray[] = $this->handlePension($item);
break;
//etc...
}
Another way would be to call variable based functions.
foreach ($json as $item) {
$returnArray[] = $crmMapKey($item);
}
function Client1Insurance($item) {
// Do something in here.
return $array;
}
function Client2Insurance($item) {
// Do something in here.
return $array;
}
Much more elegant way of doing things I feel.

Remove first element from simple array in loop

This question has been asked a thousand times, but each question I find talks about associative arrays where one can delete (unset) an item by using they key as an identifier. But how do you do this if you have a simple array, and no key-value pairs?
Input code
$bananas = array('big_banana', 'small_banana', 'ripe_banana', 'yellow_banana', 'green_banana', 'brown_banana', 'peeled_banana');
foreach ($bananas as $banana) {
// do stuff
// remove current item
}
In Perl I would work with for and indices instead, but I am not sure that's the (safest?) way to go - even though from what I hear PHP is less strict in these things.
Note that after foreach has run, I expected var_dump($bananas) to return an empty array (or null, but preferably an empty array).
1st method (delete by value comparison):
$bananas = array('big_banana', 'small_banana', 'ripe_banana', 'yellow_banana', 'green_banana', 'brown_banana', 'peeled_banana');
foreach ($bananas as $key=>$banana) {
if($banana=='big_banana')
unset($bananas[$key]);
}
2nd method (delete by key):
$bananas = array('big_banana', 'small_banana', 'ripe_banana', 'yellow_banana', 'green_banana', 'brown_banana', 'peeled_banana');
unset($bananas[0]); //removes the first value
unset($bananas[count($bananas)-1]); //removes the last value
//unset($bananas[n-1]); removes the nth value
Finally if you want to reset the keys after deletion process:
$bananas = array_map('array_values', $bananas);
If you want to empty the array completely:
unset($bananas);
$bananas= array();
it still has the indexes
foreach ($bananas as $key => $banana) {
// do stuff
unset($bananas[$key]);
}
for($i=0; $i<count($bananas); $i++)
{
//doStuff
unset($bananas[$i]);
}
This will delete every element after its use so you will eventually end up with an empty array.
If for some reason you need to reindex after deleting you can use array_values
How about a while loop with array_shift?
while (($item = array_shift($bananas)) !== null)
{
//
}
Your Note: Note that after foreach has run, I expected var_dump($bananas) to return an empty array (or null, but preferably
an empty array).
Simply use unset.
foreach ($bananas as $banana) {
// do stuff
// remove current item
unset($bananas[$key]);
}
print_r($bananas);
Result
Array
(
)
This question is old but I will post my idea using array_slice for new visitors.
while(!empty($bananas)) {
// ... do something with $bananas[0] like
echo $bananas[0].'<br>';
$bananas = array_slice($bananas, 1);
}

Remove session index php

New to php
I want to remove index with value from php session array. I'm using this code
$max=count($_SESSION['Item']);
for($i=0;$i<$max;$i++){
if(strpos($_SESSION['Item'][$i]['Name'],'Shipping')!== false)
{
unset($_SESSION['Item'][$i]);
break;
}
its working fine if value exists in last index of array. But if it exists in between. it doesn't work at all. Where am i going wrong?
Try to use array_splice, to remove items
array_splice($_SESSION['Item'], $i, 1);
I recommend using the foreach instead of for. This way your array keys can be more then only int. And is guaranteed to loop over all the array items
foreach($_SESSION['Item'] as $key => $value) {
if (strpos($value['Name'],'Shipping')!== false) {
unset($_SESSION['Item'][$key]);
}
}
As pointed out the break will stop the loop. So if you only want to remove a single entry, you should add the break
if(strpos($_SESSION['Item'][$i]['Name'],'Shipping')!== false)
{
unset($_SESSION['Item'][$i]);
}

Nested foreach loops, PHP, how do I manipulate the values?

foreach ($bing_array as $bing_array_val)
{
foreach ($final_array as $final_array_val)
{
if ($final_array_val["link"] == $bing_array_val["link"])
{
$final_array_val["rank"] += $bing_array_val["rank"];
}
}
}
The above code has two foreach loops, which are nested.
It should test every bing_array["link"] against every final_array["link"] and if they are the same, the final_array["rank"] value should be += bing_array["rank"] but when I echo final_array, the ["rank"] values are unchanged.
I assume this is a syntax problem, where am I going wrong?
Thanks
You need to use the reference syntax (& prefix):
foreach ($final_array as &$final_array_val)
{
}
unset($final_array_val);
Note that the unset is required to break the reference to the last value. Read more here.
Here is the actual code you need :
foreach ($bing_array as &$bing_array_val)
{
foreach ($final_array as &$final_array_val)
{
if ($final_array_val["link"] == $bing_array_val["link"])
{
$final_array_val["rank"] += $bing_array_val["rank"];
}
}
unset(&$final_array_val);
}
unset(&$bing_array_val);
In your initial code, each time you were looping on $final_array, it was creating a temporary value called $final_array_val containing the content. Then, you modified it, and then it was replaced for each occurence of the foreach.
By passing the variables by reference, instead of creating a new temporary variable in the foreach, you use the actual variable which will keep the modifications you have done to it.

Does php have c++'s std::pair?

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);
}

Categories