if inside for each loop pushing multidimensional array - php - php

I'm running two for each loops and pushing one of them into the other one. This works fine, except if my I have more than one match. In that case, I'm only getting the last one. Sorry about the title, not too sure how to call this question in one line.
foreach($items as &$item) {
foreach($fruits as &$fruit) {
$i = 0;
if($fruit['for']==$item['id']) {
$item["fruits"][$i] = $fruit;
$i++;
}
}
}
First array :
array(114) {
[0]=>
array(5) {
["id"]=>
string(2) "76"
...
}
...
}
Second array :
array(47) {
[0]=>
array(5) {
["id"]=>
string(1) "4"
["for"]=>
string(2) "76"
...
}
...
}
With multiple matches of the if($fruit['for']==$item['id']) logic, I'd like the following output.
array(114) {
[0]=>
array(6) {
["id"]=>
string(2) "76"
...
["fruits"]=>
array(2) {
[0]=>
array(5) {
["id"]=>
string(1) "4"
["for"]=>
string(2) "76"
...
}
[1]=>
array(5) {
["id"]=>
string(2) "33"
["for"]=>
string(2) "76"
...
}
}
}
}
What am I doing wrong?

take $i outside the loop, your match is always stored in $item["fruits"][0]
foreach($items as &$item) {
$i = 0;
foreach($fruits as &$fruit) {
if($fruit['for']==$item['id']) {
$item["fruits"][$i] = $fruit;
$i++;
}
}
}

You set $i to 0 for every array-element you check. This renders the $i++ useless and your first match gets overwritten. Try either this:
foreach($items as &$item) {
$i = 0;
foreach($fruits as &$fruit) {
if($fruit['for']==$item['id']) {
$item["fruits"][$i] = $fruit;
$i++;
}
}
}
or this: (depending on what exactly you will need)
$i = 0;
foreach($items as &$item) {
foreach($fruits as &$fruit) {
if($fruit['for']==$item['id']) {
$item["fruits"][$i] = $fruit;
$i++;
}
}
}
That way, each time you find a new match it gets a new key.

Related

How to group a multidimensional array by multiple subarray values?

I checked this question and answers:
How to group a multidimensional array by a particular subarray value?
He wanted to group results by 'level'. But how would you do it to group it by 'level' first and then by 'type'?
Its pretty straight forward. Loop through $items array. Get each item's level and type and if they are not set yet, initialize them with an empty array. Then just push the "cust" value into the array.
I have given the code below.
I am assuming "$items" is an array which contains the input.
$g = [];
foreach($items as $k => $v) {
$l = $v["level"];
$t = $v["type"];
$c = $v["cust"];
if(!isset($g[$l])) {
$g[$l] = [];
}
if(!isset($g[$l][$t])) {
$g[$l][$t] = [];
}
$g[$l][$t][] = [
"cust" => $c
];
}
var_dump($g);
The output of this code would be like below:
array(3) {
[1]=>
array(1) {
["standard"]=>
array(2) {
[0]=>
array(1) {
["cust"]=>
string(6) "XT8900"
}
[1]=>
array(1) {
["cust"]=>
string(6) "XT8944"
}
}
}
[3]=>
array(1) {
["premier"]=>
array(2) {
[0]=>
array(1) {
["cust"]=>
string(6) "XT8922"
}
[1]=>
array(1) {
["cust"]=>
string(6) "XT8816"
}
}
}
[7]=>
array(1) {
["standard"]=>
array(1) {
[0]=>
array(1) {
["cust"]=>
string(6) "XT7434"
}
}
}
}
[P.S.]: You can also use sort to solve this problem easily. That's another way of solving this problem.

Remove/unset every other key in multidimensional array but preserve keys

I have a long multidimensional array with timestamps as keys which contain arrays of values. Something like this but with more timestamps:
array(3) {
[1502609400]=>
array(2) {
["Item1"]=>
array(1) {
["PRICE"]=>
float(100)
}
["Item2"]=>
array(1) {
["PRICE"]=>
float(50)
}
}
[1502611200]=>
array(2) {
["Item1"]=>
array(1) {
["PRICE"]=>
float(200)
}
["Item2"]=>
array(1) {
["PRICE"]=>
float(150)
}
}
[1502613000]=>
array(2) {
["Item1"]=>
array(1) {
["PRICE"]=>
float(500)
}
["Item2"]=>
array(1) {
["PRICE"]=>
float(250)
}
}
How can I remove every every second array of the array without losing the keys as timestamp? So I end up with this:
array(3) {
[1502609400]=>
array(2) {
["Item1"]=>
array(1) {
["PRICE"]=>
float(100)
}
["Item2"]=>
array(1) {
["PRICE"]=>
float(50)
}
}
[1502613000]=>
array(2) {
["Item1"]=>
array(1) {
["PRICE"]=>
float(500)
}
["Item2"]=>
array(1) {
["PRICE"]=>
float(250)
}
}
If I use a for loop and unset every second key I lose all the keys and end up with 0, 1, 2 etc. instead of the timestamp.
In a loop, check for index and unset every second element:
You can use custom $index variable, like this:
$index = 0; // points to first element
foreach ($array as $key => $value) {
if ($index % 2 != 0) { //check for un-even
unset($array[$key]);
}
$index++; // move pointer to next element
}
$i=1 // where the key to remove
$x=0; //loop to determine the key position
foreach ($array as $key=>$value){
if($x==$i){
unset($array[$key]);
}
$x++;
}
In that kind of case, a simple foreach can be more efficient perfwise than a standard function :
foreach ($array as $key => $val) {
if (array_key_exists('Item2', $val)) {
unset($val['Item2']);
}
}

Combine varied number of dynamically named arrays

I have seen the following: array_merge() How can I add a 'range' of an array name and the answers don't work for me.
I have an array that I am looping through in order to slice and convert certain currency strings to float numbers. I then have to array_merge them back together in order to work with the array and have been dynamically naming them so that I don't overwrite the previous array_merge. After doing so, I then need to combine all of the dynamically named arrays into one array.
Initially I had the following code, which worked great when I only had 3 nested arrays in the $order['product'] array. However, this number varies, and the code needs to do so as well.
$nr = 1;
foreach ($order['product'] as $product) {
$product_total = array_slice($product, 1);
array_walk($product_total, "convertCurrencyStringtoNumber");
${"final_product" . $nr} = array_merge($product, $product_total);
$nr++;
};
$arrays = array($final_product1, $final_product2, $final_product3);
var_dump($arrays);
This results in the following array:
array(3) {
[0]=> array(2) {
["source_code"]=> string(10) "408000-025"
["total"]=> float(18) }
[1]=> array(2) {
["source_code"]=> string(10) "408000-025"
["total"]=> float(17) }
[2]=> array(2) {
["source_code"]=> string(10) "408000-025"
["total"]=> float(2.75) } }
How do I implement a varied number of dynamically named arrays in the line:
$arrays = array($final_product1, $final_product2, $final_product3);
I attempted the following, but the array is nested incorrectly. Feel free to fix this code or come up with a better solution.
$nr = 1;
$i = 1;
foreach ($order['product'] as $product) {
$product_total = array_slice($product, 1);
array_walk($product_total, "convertCurrencyStringtoNumber");
${"final_product" . $nr} = array_merge($product, $product_total);
if ($nr > 0) {
$arrays = $final_product1;
for ($i = 2; $i <= $nr; $i++) {
$arrays = array_merge($arrays, ${"final_product" . $nr});
}
} else {
echo "There are no products in this order";
}
$nr++;
};
var_dump($arrays);
This results in the incorrectly nested array:
array(2) {
[0]=> array(2) {
[0]=> array(2) {
["source_code"]=> string(10) "408000-025"
["total"]=> float(18) }
[1]=> array(2) {
["source_code"]=> string(10) "408000-025"
["total"]=> float(17) } }
[1]=> array(2) {
["source_code"]=> string(10) "408000-025"
["total"]=> float(2.75) } }
Simply replace your dynamically single-named variables with an array:
$final_product = array();
foreach ($order['product'] as $product) {
$product_total = array_slice($product, 1);
array_walk($product_total, "convertCurrencyStringtoNumber");
$final_product[] = array_merge($product, $product_total);
};
var_dump($final_product);
Unless I'm missing something here... this should be as easy and simple as:
$final_array=[];
foreach ($order['product'] as $product) {
$final_array[]['total'] = (float) $product['whatever value 1 is...'];
$final_array[]['source_code'] = $product['source_code'];
}
var_dump($final_array);
If you need to apply convertCurrencyStringtoNumberbecause it does something weird to the variable then changethe seccond line to:
$final_array[]['total'] = convertCurrencyStringtoNumber(array_slice($product, 1));

Is there any way to access to the 2nd level of an array?

I've created a super array which have 4 levels.
Here is the beast :
array(4) {
["arrayCoordinateur"]=>
array(2) {
["siret"]=>
array(1) {
[0]=>
string(14) "44306184100039"
}
["sigle"]=>
array(1) {
[0]=>
string(3) "NdP"
}
}
["arrayGroupMember"]=>
array(2) {
["siret"]=>
array(2) {
[0]=>
string(14) "44306184100039"
[1]=>
string(14) "44306184100039"
}
["sigle"]=>
array(2) {
[0]=>
string(7) "rerzrez"
[1]=>
string(5) "Autre"
}
}
["arrayPartEnt"]=>
array(2) {
["sigle"]=>
array(3) {
[0]=>
string(6) "Blabla"
[1]=>
string(11) "CharbonBleu"
[2]=>
string(3) "JsP"
}
["siret"]=>
array(3) {
[0]=>
string(14) "77408201000034"
[1]=>
string(14) "51133834500024"
[2]=>
string(14) "40794236600011"
}
}
["arrayPartenExt"]=>
array(2) {
["sigle"]=>
array(2) {
[0]=>
string(3) "BNN"
[1]=>
string(5) "13456"
}
["siret"]=>
array(1) {
[0]=>
string(14) "00000000000000"
}
}
}
as you can see, the structure is comped of 4 Array who have all subs array called "siret" and "sigle".
I would like to be able to loop only on those siret and sigle without being annoyed by the first level, to put them into a table.
Here is my table :
$i = 0;
foreach ($allPartenaires as $partenaire=>$data) {
for ($i=0; $i < count($data) ; $i++) {
echo "<tr>
<td>
".$data['sigle'][$i]."
</td>
<td>
".$data['siret'][$i]."
</td>
</tr>";
}
}
$allPartenaires being the super array at the beginning of this post.
This code doesn't work since all the subarray dont have the same size...
Any help would be greatly appreciated
I think this is what you need:
$data = array(
"arrayCoordinateur"=>array(
"siret"=>array(
"44306184100039",
),
"sigle"=>array(
"NdP",
),
),
"arrayGroupMember"=>array(
"siret"=>array(
"44306184100039",
"44306184100039",
),
"sigle"=>array(
"rerzrez",
"Autre",
),
),
"arrayPartEnt"=>array(
"siret"=>array(
"77408201000034",
"51133834500024",
"40794236600011",
),
"sigle"=>array(
"Blabla",
"CharbonBleu",
"JsP",
"Something",
),
),
);
echo '<table>';
foreach($data as $key => $value) {
$length = count($value['siret']) > count($value['sigle']) ? count($value['siret']) : count($value['sigle']);
for($i = 0; $i < $length; $i++) { //Now it works even if siret and single doesn't have same number of elemenets
$v1 = '-';
$v2 = '-';
if (isset($value['siret'][$i])) {
$v1 = $value['siret'][$i];
}
if (isset($value['sigle'][$i])) {
$v2 = $value['sigle'][$i];
}
echo
'
<tr>
<td>'.$v1.'</td>
<td>'.$v2.'</td>
</tr>
';
}
}
echo '</table>';
Result:
44306184100039 NdP
44306184100039 rerzrez
44306184100039 Autre
77408201000034 Blabla
51133834500024 CharbonBleu
40794236600011 JsP
- Something
nested foreach loops are what you need
foreach ($allPartenaires as $data) {
echo '<tr>';
foreach($data as $nestedArray) {
foreach($nestedArray as $content) {
echo "<td>{$content}</td>";
}
}
echo '</tr>';
}

find / select specified ID in array php

i have array with database, and have to select only this items what have "tid" = 1
array(3) {
[1]=>
array(4) {
["tid"]=> "1"
["title"]=> "Google"
["url"]=> "http://google.com/"
["description"]=> "A very efficient search engine."
}
[2]=>
array(4) {
["tid"]=> "2"
["title"]=> "Facebook"
["url"]=> "http://facebook.com/"
["description"]=> "Trade securities, currently supports nearly 1000 stocks and ETFs"
}
[3]=>
array(4) {
["tid"]=> "1"
["title"]=> "Yandex"
["url"]=> "http://yandex.ru/"
["description"]=> "Another efficient search engine popular in Russia"
}
}
how can i select only this items from array what have "tid" = 1?
<?php
$final_arr = array();
foreach($tid_arrs as $tid_arr){
if($tid_arr['tid'] == 1){
$final_arr[] = $tid_arr;
}
}
print_r($final_arr);
?>
$filteredArray = array();
for($i = 0, $end = count($array);$i < $end;i++)
{
if($array[$i]["tid"] === "1")
{
$filderedArray[] = $array[$i];
}
}
That way $filteredArray will contain solely the items with tid 1;
Try array_filter function: http://php.net/manual/en/function.array-filter.php this should help.
print_r(array_filter($array, "filter_function"));
function filter_function($element){
return (int)$element['tid'] === 1;
}
let's say you starting array is $arr.
$result = array();
foreach ($arr as $arrItem) {
if ((array_key_exists('tid', $arrItem)) && ($arrItem['tid'] == "1")){
$result[] = $arrItem;
}
}
$result should be what you are excepted.

Categories