advanced unset the value form array PHP - php

I have two arrays, what consist arrays. I need to merge these arrays recursive. But I need to do this action few times, and
array_merge_recursive()
will apend my data twice, I want to remove element what already exist in target array.
$messages array :
array(2) {
["messages"]=>
array(2) {
["test.testik"]=>
string(13) "Це тест"
["test2313.tes31231tik"]=>
string(23) "це тестончик"
}
["validators"]=>
array(4) {
["valid.validik"]=>
string(36) "Це валідне значення"
["joga.jimbo"]=>
string(27) "Джімбо торбінс"
["validka.invalidka"]=>
string(23) "це інвалідка"
["smith.john"]=>
string(17) "джон сміт"
}
}
$allCar array:
array(2) {
["messages"]=>
array(1) {
["test2313.tes31231tik"]=>
string(23) "це тестончик"
}
["validators"]=>
array(2) {
["validka.invalidka"]=>
string(23) "це інвалідка"
["smith.john"]=>
string(17) "джон сміт"
}
}
I wrote some code:
foreach ($messages as $domain => $messagesArray) {
foreach ($allCat as $d => $mess) {
if ($domain == $d) {
foreach ($messagesArray as $ymlkey => $trans) {
foreach ($mess as $ymlk => $transl) {
if ($ymlkey == $ymlk) {
unset($mess[$ymlk]);
}
}
}
}
}
}
Then when I run recursive merge it append the same values to array. What I am doing wrong ?

This:
foreach ($allCat as $d => $mess) {
$mess is a temporary COPY of whatever value your foreach() loop is currently working on. When you do your unset($mess...) later on, you're simply unsetting that temporary copy.
While some might suggest making $mess a reference, this can/will cause problems later on, because $mess will STILL be a reference after the loops end, and reusing the variable later on will now be mucking around with whatever $mess last pointed at in the loop.
Instead, use the full array/object path reference in the unset call:
unset($messages[$domain][$d][$ymlkey][$ymkl])
or whatever it should be. This way you guarantee you're working with the actual "real" array, and not any of the many temporary copies your nested loops are creating.

Related

foreach results in endless loop

I have an array stored in $_SESSION:
var_dump($_SESSION['session_article']);
//result:
array(2) {
[0]=> array(2) {
["id"]=> string(1) "3"
["amount"]=> int(2)
}
[1]=> array(2) {
["id"]=> string(2) "13"
["amount"]=> int(1)
}
}
If I do:
for($artKey = 0;$artKey < count($_SESSION['session_article']);$artKey++){
$cartArt = $_SESSION['session_article'][$artKey];
//stuff that doesn't affect key or value
}
everything is fine ...but if I do:
foreach($_SESSION['session_article'] as $artKey => $cartArt){
//stuff that doesn't affect key or value
}
the page won't stop to load (infinite loading, like the foreach never terminates)
I would like to you know that the computer is not a dumb machine, so whenever you do not get the right result then its not the computers problem, it is in how you code.
So lets take a look at your code first you var_dump($_SESSION['session_article']) you got an array with two elements each being an associative array. Now observe that this is an array of arrays so you code in scenario 2 is wrong.
If it were to be just a single array say $myArray = ['Simon', 'Peter', 'You'] then this woul have worked fine (note I used the short array syntax here you can use array() if you prefer). But the problem is you have multidimensional Arrays so you could should be
foreach($_SESSION['session_article'], list($a,))
{
//stuffs here
}
or better walk through the $_SESSION['session_article'] as an associative array like so
$myArray = $_SESSION['session_article']
$field = count($myArray, COUNT_RECURSIVE - (int)2)
for ($record = 0; $record < $myArray.length; $record++) {
//record number
for ($field = 0; $field < $field ; $field++) {
//combine record and field here
}
}
Hope I could lend a helping hand?
Please checkout
http://php.net/manual/en/function.count.php
http://php.net/manual/en/control-structures.foreach.php
They really have a good doc, just take you time.

Dealing with php array whose content may or may not have another array

I am dealing with arrays whose structure is different depending on the number or items in the array.
For example, the following is the array with one item in it.
// Case #1
["Assignment"]=>
object(stdClass)#29 (9) {
["Id"]=> string(10) "1234567890"
..
}
However if there are more than 1 item in the array,
// Case #2
["Assignment"]=>
array(2) {
[0]=>
object(stdClass)#28 (9) {
["Id"]=> string(10) "1234567890"
..
}
[1]=>
object(stdClass)#28 (9) {
["Id"]=> string(10) "1234567890"
..
}
}
Notice that the contents are in another array for this. No matter of how many items there are, I want to access the Id. $array->Id will work for one case but won't work for the other with the error saying, Trying to get property of non-object.
I could come up with an inefficient way by counting the # of contents in the array like this:
// say the arrays above are declared as $assignment
if($numOfAssignment > 1) {
foreach($assignment as $key) {
echo $key->Id;
}
}
else {
echo $assignment->Id;
}
But if the code was a bit lengthy, I feel it is too repetitive and inefficient.
Is there a way to do this in one effective phrase no matter of the number of the contents inside the array? Let me know if anything is unclear. Thanks!
What you can do is change the non-array into an array with a single element, then you can process it consistently.
if (!is_array($assignment)) {
$assignment = array($assignment);
}
foreach ($assignment as $key) {
echo $key=>Id;
}

How to merge specific key to one array with PHP?

I need to get that value in the array with "clean_bin_number" and pull it out from each of the main arrays. And have only the values in one array.
Hopefully you guys can understand what I'm trying to do....
Here some code examples:
array(2) {
[0]=>
array(1) {
["clean_bin_number"]=>
array(1) {
[0]=>
array(1) {
[0]=>
string(7) "1004445"
}
}
}
[1]=>
array(1) {
["clean_bin_number"]=>
array(1) {
[0]=>
array(1) {
[0]=>
string(7) "3087762"
}
}
}
}
I'd like to get a result like that:
array {
[0] => "1004445",
[1] => "3087762"
}
Thanks
Here are some ways to go about what you want to achieve:
array_walk array_map for foreach
Hint:
foreach($array as $inner)
{
$bin = $inner["clean_bin_number"][0][0];
// ...
}
So your input array is:
$input = array(
array("clean_bin_number" => array(array("1004445")) ),
array("clean_bin_number" => array(array("3087762")) )
);
Now you can very easily just iterate over that array and extract the routes/parts you need, or if those exist not only once, iterate over the sub parts.
Example:
$new_arr = array();
foreach ($input as $element) {
$new_arr[] = $element['clean_bin_number'][0][0];
}
See this working here.
You should have been able to find another solution thou. If not, you have clearly not finished reading/watching beginner tutorials for PHP. Go do that if you want to keep working with PHP. Find Tutorials online like this youtube video or this article.
Asking questions to get specific solutions takes longer than actually doing a bit of learning if you ask me.

foreach loop over multidimensional associative array

I have an array ($this->taxBand) which has 3 key => value pairs. Each value is another array:
array(3) {
["basic"]=>
array(3) {
["rate"]=>
int(20)
["start"]=>
int(0)
["end"]=>
int(31865)
}
["higher"]=>
array(3) {
["rate"]=>
int(40)
["start"]=>
int(31866)
["end"]=>
int(150000)
}
["additional"]=>
array(3) {
["rate"]=>
int(45)
["start"]=>
int(150001)
["end"]=>
NULL
}
}
I need to loop through not only the keys "basic", "higher" and "additional" but the arrays within them too.
I'll be comparing the "start" and "end" values with another variable and applying a calculation based on the "rate".
I've tried nested foreach in a couple of different ways using many examples I've found here and the official documentation and can only ever get it to return the "basic" array elements.
Example:
foreach ($this->taxBand as $key => $band) {
foreach ($band as $subKey => $value) {
// Do my stuff
}
}
If I return $band, I get:
array(5) {
["rate"]=>
int(20)
["start"]=>
int(0)
["end"]=>
int(31865)
}
And $key returns:
string(5) "basic"
I'm clearing missing something quite basic and not fully understanding how to loop through these arrays properly and get all the data I need.
Any help would be much appreciated. :)
EDIT: Trying to show an example of how I plan to use this loop. It's difficult because of the other functions/variables:
foreach ($this->taxBand as $key => $band) {
if ($band["end"] !== null || $band["end"] > 0) {
$band["amount"] = $this->get_lower_figure($this->totalTaxableAmount, $band["end"]) - $bandDeductions;
} else {
$band["amount"] = $this->totalTaxableAmount - $bandDeductions;
}
$band["percentage_amount"] = ($band["amount"] / 100) * $band["rate"];
$totalDeduction += $band["percentage_amount"];
$bandDeductions += $band["amount"];
return $totalDeduction;
}
Assuming $this->totalTaxableAmount is 40000 the "percentage_amount" should return a float of 6373, which it does, for the basic band. But it should also return 3254 from the higher band.
get_lower_figure() just takes two arguments and checks which is less than the other.
You seem to be going about everything right..but if you are going to be using the start/end/rate values directly, you shouldn't need the second foreach loop. Something like this should get you going:
$values = array();
foreach($this->taxBand as $key => $band) {
$calculation = ($band['end'] - $band['start']) / $band['rate'];
$values[$key] = $calculation;
}
return $values;
I'm doubting this is the work you plan to do, but the point is you can access the inner associative array $band directly.
If you were to use a sub-loop for whatever reason, you could do something like this:
foreach($this->taxBand as $key => $band) {
// Set variables for this band
foreach($band as $subKey => $value) {
switch($subKey) {
case 'start': // do something
break;
case 'end': // do something
break;
case 'rate': // do something
break;
}
}
// Calculations finished
}

How to rename the key in a foreach loop?

I'm trying to generate an XML from a database call, and the utility class I'm using throws an error Illegal character in tag name. tag: 0
I figured this is because of the array being [0],[1],[2] etc. Really I should set them all to be something standard, like 'asset' since they are all assets, but I can't do that because then keys will be identical, but maybe the ID would work. But I don't know how to change the key that I'm on within a foreach loop.
I tried:
foreach ($assets as &$key => &$asset) {
$key2 = $asset->isci;
$asset = get_object_vars($asset);
}
But I cannot pass reference for $key.
This is a brief representation of what the array looks like:
array(2) {
[0]=>
array(25) {
["id"]=>
string(2) "27"
}
[1]=>
array(25) {
["id"]=>
string(2) "25"
}
[2]=>
array(25) {
["id"]=>
string(1) "1"
}
}
Modifying keys of an array while looping over it is generally a bad idea - even if the language supported it, it can be very confusing to debug.
The simplest approach is to simply build a new array based on the old one, but with better keys:
$rekeyed_assets = array();
foreach ($assets as $old_key => $asset)
{
$new_key = $asset->isci;
$asset = get_object_vars($asset);
$rekeyed_assets[ $new_key ] = $asset;
}
The most convenient way is to change all the keys and then use array_combine to create a new array with the modified keys. Here's how you can do that in bulk using array_map and an anonymous function:
$newKeys = array_map(function($asset) { return $asset->isci; }, $assets);
$assets = array_combine($newKeys, $assets);
You can also do the same for the values:
$newKeys = array_map(function($asset) { return $asset->isci; }, $assets);
$newValues = array_map(function($asset) { return get_object_vars($asset); }, $assets);
$assets = array_combine($newKeys, $newValues);
This method does have a drawback (increased memory usage) which may be an issue if your array has millions of items, but in that case it's highly likely that it would be better to restructure the program so that it does not need to keep huge arrays in memory in the first place.

Categories