arrays with dif keys inside 1 array - php

like the question says, I have 2 foreach cycles, 1 cycle iterates an array with 4 keys, and the other one an array with 3 keys, how to get this two arrays in only 1 ?
I have this
....
],
],
'Detalle' => array()
];
foreach ($datos["line_items"] as $line => $item) {
$tempArray = array(
'NmbItem' => $item['name'],
'QtyItem' => $item['quantity'],
'PrcItem' => $item['price'],
'IndExe' => 1
);
}
foreach($datos["fee_lines"] as $line => $fee){
$tempArray=array(
'NmbItem' => $fee['name'],
'QtyItem' => 1,
'PrcItem' => $fee['total']
);
}
$dte['Detalle'][] = $tempArray;
}
if you notice the second array cycle doesnt contain 'indexe' key, after asign this tempArray in $dte['Detalle'][] = $tempArray only works with the last cycle, or the first one if I remove the second.
the output should be something like:
temp = Array (
array[0]
'NmbItem => name',
'QtyItem'=> 10,
'PrcItem'= 1000,
'IndExe' => 1
array[1]
'NmbItem => another name',
'QtyItem'=> 5,
'PrcItem'=> 3000
)

To make it work with your code, you should also add $dte['Detalle'][] = $tempArray; after the first loop.
The issue is that you are setting the $tempArray in each foreach so you end up with only the last one when assigning it in the $dte['Detalle'].
So, something like this should work:
foreach ($datos["line_items"] as $line => $item) {
$tempArray = array(
'NmbItem' => $item['name'],
'QtyItem' => $item['quantity'],
'PrcItem' => $item['price'],
'IndExe' => 1
);
}
$dte['Detalle'][] = $tempArray;
foreach($datos["fee_lines"] as $line => $fee){
$tempArray=array(
'NmbItem' => $fee['name'],
'QtyItem' => 1,
'PrcItem' => $fee['total']
);
}
$dte['Detalle'][] = $tempArray;
However, I would do it using the array_map function.
Docs for array_map
You can have it something like this:
<?php
$data_1 = array_map(function($item){
return array(
'NmbItem' => $item['name'],
'QtyItem' => $item['quantity'],
'PrcItem' => $item['price'],
'IndExe' => 1
);
}, $datos["line_items"]);
$data_2 = array_map(function($fee){
return array(
'NmbItem' => $fee['name'],
'QtyItem' => 1,
'PrcItem' => $fee['total']
)
}, $datos["fee_lines"]);
$dte['Detalle'] = array_merge($dte['Detalle'], $data_1, $data_2);

Related

Merge arrays in multidimensional array based on multiple values

[
0 => [
'qty' => 10
'section' => 'VK7B'
'time_window' => 1
]
1 => [
'qty' => 1
'section' => 'STIC'
'time_window' => 1
]
2 => [
'qty' => 1
'section' => 'STIC'
'time_window' => 1
]
]
I have this multidimensional array where I want to merge the array's if both the section and the time_window are the same, summing the qty for that array. What is an elegant way to do this?
I have tried this ($sections being the multidimensional arry), but this changes the keys and only checks for one value:
$new = []
foreach ($sections as $s) {
if (isset($new[$s['section']])) {
$new[$s['section']]['qty'] += $s['qty'];
$new[$s['section']]['time_window'] = $s['time_window'];
} else {
$new[$s['section']] = $s;
}
}
[
'VK7B' => [
'qty' => 10
'section' => 'VK7B'
'time_window' => 1
]
'STIC' => [
'qty' => 2
'section' => 'STIC'
'time_window' => 1
]
]
As pointed by #RiggsFolly in the comment you are not checking time_window are the same.
You can do it with this code:
$new = []
foreach ($sections as $s) {
// you need to save both values (section and time_window) to check both of them
if (isset($new[$s['section'].$s['time_window']])) {
$new[$s['section'].$s['time_window']]['qty'] += $s['qty'];
$new[$s['section'].$s['time_window']]['time_window'] = $s['time_window'];
} else {
$new[$s['section'].$s['time_window']] = $s;
}
}
// Now $new is an associative array => let's transform it in a normal array
$new = array_values($new);

How can I achieve this in Array in PHP

am having problem achieving this result with array, I want to update another empty array with data in first array in such a way that the first two rows is ommitted and the first 3rows is added to the index 0 of the empty array, and the next 3 rows is also updated to the second index and so on. I have this Array in
`$arr = [
'tqty' => 9,
'tPrice' => 18700,
'food_name_1' => 'Black Coffee',
'food_quanty_1' => 1,
'food_price_1' => 1000,
'food_name_2' => 'Sub Combo',
'food_quanty_2' => 2,
'food_price_2' => 3000
];`
I want to use this array data and update another empty array this way, removing the first two rows
$arr2 = [
0 => [
'food_name_1' => 'Black Coffee',
'food_quanty_1' => 1,
'food_price_1' => 1000
],
1 => [
'food_name_2' => 'Sub Combo',
'food_quanty_2' => 2,
'food_price_2' => 3000
]
];
here is my code so far
$arr = [
'tqty' => 9,
'tPrice' => 18700,
'food_name_1' => 'Black Coffee',
'food_quanty_1' => 1,
'food_price_1' => 1000,
'food_name_2' => 'Sub Combo',
'food_quanty_2' => 2,
'food_price_2' => 3000
];
$newdat = [];
$count = 0;
$oldcount = 1;
foreach($arr as $key => $value){
if(preg_match_all('!\d+!', $key, $matches)){
if($oldcount == $matches[0][0]){
$newdat[$matches[0][0]] = [
$count => [
$key => $value
]
];
} else{
$count = 0;
$oldcount = $matches[0][0];
}
}
$count++;
}
I hope I get help soon. thanks
Assuming the array keys and order stay consistent you could use array_chunk
<?php
$inArray = [
'tqty' => 9,
'tPrice' => 18700,
'food_name_1' => 'Black Coffee',
'food_quanty_1' => 1,
'food_price_1' => 1000,
'food_name_2' => 'Sub Combo',
'food_quanty_2' => 2,
'food_price_2' => 3000,
];
$outArray = [];
// Remove first 2 values.
$inArray = array_slice( $inArray, 2 );
// 'Chunk' the rest of the values.
// true preserves keys.
$outArray = array_chunk( $inArray, 3, true );
echo '<pre>' . print_r( $outArray, true ) . '</pre>';
/**
Output:
<pre>Array
(
[0] => Array
(
[food_name_1] => Black Coffee
[food_quanty_1] => 1
[food_price_1] => 1000
)
[1] => Array
(
[food_name_2] => Sub Combo
[food_quanty_2] => 2
[food_price_2] => 3000
)
)
</pre>
*/
If I have understood you correctly,
$newdata = array();
for ($i = 1; $i++;) { // Intentionally no condition set.
if (array_key_exists('food_name_' . $i, $arr)) {
$temparray = array();
$temparray['food_name_' . $i] = $arr['food_name_' . $i];
if (array_key_exists('food_quanty_' . $i, $arr)) {
$temparray['food_quanty_' . $i] = $arr['food_quanty_' . $i];
}
if (array_key_exists('food_price_' . $i, $arr)) {
$temparray['food_price_' . $i] = $arr['food_price_' . $i];
}
$newdata[] = $temparray;
} else {
break; // break out of the loop
}
}
echo "<pre>";
print_r($newdata);
echo "</pre>";
die();
Loop through it and build the array index string via variables.
<?php
$arr = [
'tqty' => 9,
'tPrice' => 18700,
'food_name_1' => 'Black Coffee',
'food_quanty_1' => 1,
'food_price_1' => 1000,
'food_name_2' => 'Sub Combo',
'food_quanty_2' => 2,
'food_price_2' => 3000
];
foreach(array("food_name_","food_quanty_","food_price_") as $v){
// replace the set value of 2 here with a count() on the $arr
// and some basic math - IF you are always sure you'll have 3 fields
for($i=0;$i<2;$i++){
$newarr[$i][$v.($i+1)]=$arr[$v.($i+1)];
}
}
print_r($newarr);
?>
Here's a solution that will locate the _x at the end to check its a digit
This solution does not worry about how many non numbered fields you have, or how many fields there are per numbered "row", they are also indexed based on the _x number.
$arr = [
'tqty' => 9,
'tPrice' => 18700,
'food_name_1' => 'Black Coffee',
'food_quanty_1' => 1,
'food_price_1' => 1000,
'food_name_2' => 'Sub Combo',
'food_quanty_2' => 2,
'food_price_2' => 3000
];
$arr2 = array();
foreach( $arr as $key => $value )
{
$explode = explode( '_', $key );
if( ctype_digit( $index = end( $explode ) ) === true)
{
if( isset( $arr2[ $index ] ) === false )
{
$arr2[ $index ] = array();
}
$arr2[ $index ][ substr( $key, 0, strlen( $key ) - 1 - strlen( $index ) ) ] = $value;
}
}
print_r( $arr2 );
Output:
Array
(
[1] => Array
(
[food_name] => Black Coffee
[food_quanty] => 1
[food_price] => 1000
)
[2] => Array
(
[food_name] => Sub Combo
[food_quanty] => 2
[food_price] => 3000
)
)
If you already know that you need always the same indexes from $arr, you can use the array_keys function in order to index the associative array.
Example:
$keys = array_keys($arr);
echo '<br><br>'.$arr[$keys[1]];
Here is a complete example:
$keys = array_keys($arr); #stores the associative keys by index
$arr2 = array();
/* For each array $arr do the following */
$limit = 5; #substitute this with: count($arraylist)
for( $n_array=0; $n_array<limit; $n_array++ ){
$cur_arr = array(); #substitute with your: $arraylist[ $n_array ]
for( $a = 2; $a<count($arr); $a++ ){
$cur_arr[ $keys[$a] ] = $arr[ $keys[$a] ];
}
$arr2[ $n_array ] = $cur_arr;
}
Hope it will be helpful

How to check if a value exists in a Multidimensional array

I have an Multidimensional array that takes a similar form to this array bellow.
$shop = array( array( Title => "rose",
Price => 1.25,
Number => 15
),
array( Title => "daisy",
Price => 0.75,
Number => 25,
),
array( Title => "orchid",
Price => 1.15,
Number => 7
)
);
I would like to see if a value I'm looking for is in the array, and if so, return the position of the element in the array.
Here's a function off the PHP Manual and in the comment section.. Works like a charm.
<?php
function recursive_array_search($needle,$haystack) {
foreach($haystack as $key=>$value) {
$current_key=$key;
if($needle===$value OR (is_array($value) && recursive_array_search($needle,$value) !== false)) {
return $current_key;
}
}
return false;
}
Found this function in the PHP docs: http://www.php.net/array_search
A more naive approach than the one showed by Zander, you can hold a reference to the outer key and inner key in a foreach loop and store them.
$outer = "";
$inner = "";
foreach($shop as $outer_key => $inner_array){
foreach($inner_array as $inner_key => $value) {
if($value == "rose") {
$outer = $outer_key;
$inner = $inner_key;
break 2;
}
}
}
if(!empty($outer)) echo $shop[$outer][$inner];
else echo "value not found";
You can use array_map with in_array and return the keys you want
$search = 1.25;
print_r(
array_filter(array_map(function($a){
if (in_array($search, $a)){
return $a;
}
}, $shop))
);
Will print:
Array
(
[0] => Array
(
[Title] => rose
[Price] => 1.25
[Number] => 15
)
)
php >= 5.5
$shop = array( array( 'Title' => "rose",
'Price' => 1.25,
'Number' => 15
),
array( 'Title' => "daisy",
'Price' => 0.75,
'Number' => 25,
),
array( 'Title' => "orchid",
'Price' => 1.15,
'Number' => 7
)
);
$titles = array_column($shop,'Title');
if(!empty($titles['rose']) && $titles['rose'] == 'YOUR_SEARCH_VALUE'){
//do the stuff
}

how to find a element in a nested array and get its sub array index

when searching an element in a nested array, could i get back it's 1st level nesting index.
<?php
static $cnt = 0;
$name = 'victor';
$coll = array(
'dep1' => array(
'fy' => array('john', 'johnny', 'victor'),
'sy' => array('david', 'arthur'),
'ty' => array('sam', 'joe', 'victor')
),
'dep2' => array(
'fy' => array('natalie', 'linda', 'molly'),
'sy' => array('katie', 'helen', 'sam', 'ravi', 'vipul'),
'ty' => array('sharon', 'julia', 'maddy')
)
);
function recursive_search(&$v, $k, $search_query){
global $cnt;
if($v == $search_query){
/* i want the sub array index to be returned */
}
}
?>
i.e to say, if i'am searching 'victor', i would like to have 'dep1' as the return value.
Could anyone help ??
Try:
$name = 'victor';
$coll = array(
'dep1' => array(
'fy' => array('john', 'johnny', 'victor'),
'sy' => array('david', 'arthur'),
'ty' => array('sam', 'joe', 'victor')
),
'dep2' => array(
'fy' => array('natalie', 'linda', 'molly'),
'sy' => array('katie', 'helen', 'sam', 'ravi', 'vipul'),
'ty' => array('sharon', 'julia', 'maddy')
)
);
$iter = new RecursiveIteratorIterator(new RecursiveArrayIterator($coll), RecursiveIteratorIterator::SELF_FIRST);
/* These will be used to keep a record of the
current parent element it's accessing the childs of */
$parent_index = 0;
$parent = '';
$parent_keys = array_keys($coll); //getting the first level keys like dep1,dep2
$size = sizeof($parent_keys);
$flag=0; //to check if value has been found
foreach ($iter as $k=>$val) {
//if dep1 matches, record it until it shifts to dep2
if($k === $parent_keys[$parent_index]){
$parent = $k;
//making sure the counter is not incremented
//more than the number of elements present
($parent_index<$size-1)?$parent_index++:'';
}
if ($val == $name) {
//if the value is found, set flag and break the loop
$flag = 1;
break;
}
}
($flag==0)?$parent='':''; //this means the search string could not be found
echo 'Key = '.$parent;
Demo
This works , but I don't know if you are ok with this...
<?php
$name = 'linda';
$col1=array ( 'dep1' => array ( 'fy' => array ( 0 => 'john', 1 => 'johnny', 2 => 'victor', ), 'sy' => array ( 0 => 'david', 1 => 'arthur', ), 'ty' => array ( 0 => 'sam', 1 => 'joe', 2 => 'victor', ), ), 'dep2' => array ( 'fy' => array ( 0 => 'natalie', 1 => 'linda', 2 => 'molly', ), 'sy' => array ( 0 => 'katie', 1 => 'helen', 2 => 'sam', 3 => 'ravi', 4 => 'vipul', ), 'ty' => array ( 0 => 'sharon', 1 => 'julia', 2 => 'maddy', ), ), );
foreach($col2 as $k=>$arr)
{
foreach($arr as $k1=>$arr2)
{
if(in_array($name,$arr2))
{
echo $k;
break;
}
}
}
OUTPUT :
dept2
Demo

Filter multidimensional array by lowest price

I'm working with an array that I'd like to filter so it only contains the lowest prices per key. So 50 would only have one unit, same with 100, and that unit would be the lowest price.
Here's an example of what I'm working with:
$units = [
50 => [
41788 => ['StdRate' => 231.0000, 'UnitName' => "NN23"],
46238 => ['StdRate' => 303.0000, 'UnitName' => "1038"],
46207 => ['StdRate' => 303.0000, 'UnitName' => "1007"]
],
100 => [
41570 => ['StdRate' => 299.0000, 'UnitName' => "HH18"],
46214 => ['StdRate' => 388.0000, 'UnitName' => "1014"]
]
];
I wanted to avoid doing this with a complicated foreach loop, so I thought an array_filter would be nice, but having a hard time wrapping my head around it. Or would a foreach be best?
$filtered = array_filter($units, function($a) {
});
Expected Output:
[
50 => [
41788 => ['StdRate' => 231.0000, 'UnitName' => "NN23"]
],
100 => [
41570 => ['StdRate' => 299.0000, 'UnitName' => "HH18"]
]
];
Here is a function that will go through your multi-dimensional array and grab the lowest units. It will retain the key of the big array (50, 100) and the key of the unit it grabbed (41788, 41570). It will not retain multiple values of the same low rate. In those cases it will return the first of the lowest value it found. Might not be exactly what you want, but it should be a good start and you can always modify it later. It uses a nested foreach to get its work done.
Hope this help you out!
function findLows($big) {
$lowUnits = array();
foreach($big as $id => $array) {
$low = false;
$prev = false;
foreach($array as $k => $a) {
if(!$low) {
$low = $k;
$prev = $a['StdRate'];
} else {
if($a['StdRate'] < $prev) {
$prev = $a['StdRate'];
$low = $k;
}
}
}
$lowUnits[$id] = array( $low => $array[$low]);
}
return $lowUnits;
}
$bigArray = array();
$bigArray[50][41788] = array('StdRate' => 231.0000, 'UnitName' => "NN23");
$bigArray[50][46238] = array('StdRate' => 303.0000, 'UnitName' => "1038");
$bigArray[50][46207] = array('StdRate' => 303.0000, 'UnitName' => "1007");
$bigArray[100][41570] = array('StdRate' => 299.0000, 'UnitName' => "HH18");
$bigArray[100][46214] = array('StdRate' => 388.0000, 'UnitName' => "1014");
$filtered = findLows($bigArray);
var_dump($filtered);
Will produce:
array(2) {
[50]=>
array(1) {
[41788]=>
array(2) {
["StdRate"]=>
float(231)
["UnitName"]=>
string(4) "NN23"
}
}
[100]=>
array(1) {
[41570]=>
array(2) {
["StdRate"]=>
float(299)
["UnitName"]=>
string(4) "HH18"
}
}
}
For an array with 1 fewer levels of depth, you could have directly iterated the data with array_filter(). Because you want to filter each set of data relating to first level entries, you just need to nest the array_filter() inside of array_map() (for a functional-style script).
I am going to isolate the StdRate values in each set and determine the lowest value by calling min() on the temporary array generated by array_column().
To pass the $min value into the filter's scope, use use().
This snippet will potentially return multiple deep subarrays for a respective set of data IF there is a tie among the lowest values in the set.
Code: (Demo)
$units = [
50 => [
41788 => ['StdRate' => 231.0000, 'UnitName' => "NN23"],
46238 => ['StdRate' => 303.0000, 'UnitName' => "1038"],
46207 => ['StdRate' => 303.0000, 'UnitName' => "1007"]
],
100 => [
41570 => ['StdRate' => 299.0000, 'UnitName' => "HH18"],
46214 => ['StdRate' => 388.0000, 'UnitName' => "1014"]
]
];
var_export(
array_map(
function($unit) {
$min = min(array_column($unit, 'StdRate'));
return array_filter(
$unit,
function($row) use ($min) {
return $row['StdRate'] == $min;
}
);
},
$units
)
);
Output:
array (
50 =>
array (
41788 =>
array (
'StdRate' => 231.0,
'UnitName' => 'NN23',
),
),
100 =>
array (
41570 =>
array (
'StdRate' => 299.0,
'UnitName' => 'HH18',
),
),
)

Categories