Explode and transpose nominated comma-separated strings of an associative array - php

I have an array with comma-separated values like below:
array:5 [
"manufacturer" => "BB"
"width" => "245,225, ..."
"height" => "45,65, ..."
"diameter" => "19,17, ..."
"type" => "AA"
]
There is no limit to how many comma-separated values there may be, but all 3 of them will have same length.
From this, I want to get transposed output like below:
[
245,
45,
19,
],
[
45,
65,
17
]
So far, I have tried following code.
$mandatoryFields = [
'width',
'height',
'diameter',
];
$finalArray = [];
for ($i = 0; $i < 2; $i+=1) {
foreach ($mandatoryFields as $mandatoryField) {
$fieldArray = explode(',', $executionArray[$mandatoryField]);
$finalArray[] = [
$fieldArray[$i]
];
}
}
dd($finalArray);
But it is returning me:
array:6 [
0 => array:1 [
0 => "245"
]
1 => array:1 [
0 => "45"
]
2 => array:1 [
0 => "19"
]
3 => array:1 [
0 => "225"
]
4 => array:1 [
0 => "65"
]
5 => array:1 [
0 => "17"
]
]

The following logic might help you solve your issue:
<?php
$arr = [
"manufacturer" => "BB",
"width" => "245, 225",
"height" => "45, 65",
"diameter" => "19, 17",
"type" => "AA",
];
foreach ($arr as $key => $val) {
$split[$key] = explode(',', $val);
}
$mandatoryFields = [
'width',
'height',
'diameter',
];
// keep only mandatory fields
$split = array_intersect_key($split, array_flip($mandatoryFields));
$items = count($split[$mandatoryFields[0]]); // number of 'items' per mandatory field
for ($i = 0; $i < $items; $i++) {
$result[$i] = array_column($split, $i);
}
echo '<pre>';
print_r($result);
echo '</pre>';
Output:
Array
(
[0] => Array
(
[0] => 245
[1] => 45
[2] => 19
)
[1] => Array
(
[0] => 225
[1] => 65
[2] => 17
)
)

Essentially, this is an "explode & transpose" task. If the required columns are known, then they can be hardcoded like this: (Demo)
var_export(
array_map(
null,
explode(', ', $arr['width']),
explode(', ', $arr['height']),
explode(', ', $arr['diameter'])
)
);
Output:
array (
0 =>
array (
0 => '245',
1 => '45',
2 => '19',
),
1 =>
array (
0 => '225',
1 => '65',
2 => '17',
),
)
If the columns need to be dynamic, then map the required fields, explode on commas and unpack the generated rows to maintain a functional coding style: (Demo)
var_export(
array_map(
null,
...array_map(
fn($f) => explode(', ', $arr[$f]),
$mandatoryFields
)
)
);

Related

Sum array elements in two dimensional array with duplicate element value

I have a multi array that has some duplicated values that are same by payment_name ( payment_name is an element )
I want to sum quantity of each array that has same payment_name and display the amount as one. For now the sum comes as array of all amounts. Any assistance will be highly appreciated.
var_export($num) results looks like this
array(
'items' => array (
'2020-08-04' => array (
0 => array (
0 => array (
'payment_name' =>'Cash',
'amount_paid' => array (
0 => '0',
),
),
),
1 => 0,
),
'2020-08-05' => array (
0 => array(
0 => array (
'payment_name' => 'Cash',
'amount_paid' => array (
0 => '0',
1 => '0',
2 => '165',
),
),
1 => array (
'payment_name' => 'Mpesa',
'amount_paid' => array (
0 => '0',
1 => '0',
2 => '165',
),
),
),
1 => 165,
),
My expected array should be like this, the amount paid should be the total, not an array of all amounts:
"2020-08-05" => array:2 [▼
0 => array:2 [▼
0 => array:2 [▼
"payment_name" => "Cash"
"amount_paid" => "0"
]
1 => array:2 [▼
"payment_name" => "Mpesa"
"amount_paid" => "165"
]
]
]
1 => 165
]
My code is as below
$requests = $builder->get()->groupBy('date');
$num = $requests->map(function ($row) {
$result = array();
$ttl = $row->sum('amount_paid');
$row = $row->toArray();
$names = array_column($row, 'payment_name');
$amount = array_column($row, 'amount_paid');
$unique_modes = array_unique($names);
foreach ($unique_modes as $name) {
$this_keys = array_keys($names, $name);
$qty = array_sum((array_intersect_key($amount, array_combine($this_keys, $this_keys))));
$result[] = array("payment_name"=>$name, "amount_paid"=>$amount);
}
return [$result, $ttl ];
});
return $num;
I fixed my problem using the code below:
$num = $requests->map(function ($row) {
$result = array();
$ttl = $row->sum('amount_paid');
$row = $row->toArray();
$final_array = [];
foreach($row as $arr){
$final_array[$arr['payment_name']]['payment_name'] = $arr['payment_name'];
$final_array[$arr['payment_name']]['amount_paid'] = (isset($final_array[$arr['payment_name']]['amount_paid']))? $final_array[$arr['payment_name']]['amount_paid']+$arr['amount_paid'] : $arr['amount_paid'];
}
$final_array = array_values($final_array);
return [$final_array, $ttl];
});

How to insert items into existing array

Assume I have two arrays as below
array:2 [
0 => {#1995
+"id": 6
+"sales_target_amount": "30000.00"
}
1 => {#1996
+"id": 10
+"sales_target_amount": "1000.00"
}
]
second array
array:2 [
0 => {#1994
+"sales_total": "4165.80"
+"staff_id": 6
}
1 => {#1513
+"sales_total": "1335.60"
+"staff_id": 10
}
]
I'm trying to insert the first array sales_target_amount into the second array if the id is matched to the staff_id.
code
$sum = array_merge($second_array[],$firs_array);
The code above will merge the two array together but not insert the items based on the id.
Expected Result
array:2 [
0 => {#1994
+"sales_total": "4165.80"
+"staff_id": 6
+"sales_target_amount": "30000.00"
}
1 => {#1513
+"sales_total": "1335.60"
+"staff_id": 10
+"sales_target_amount": "1000.00"
}
]
Here is the snippet, please see inline doc for explanation
$arr = [
0 => ["sales_total" => "4165.80", "staff_id" => 6],
1 => ["sales_total" => "1335.60", "staff_id" => 10],
];
$arr1 = [
0 => ["id" => 6, "sales_target_amount" => "30000.00"],
1 => ["id" => 10, "sales_target_amount" => "1000.00"],
];
//NULL to return complete arrays or objects and staff id will be key
$arr = array_column($arr, null, 'staff_id');
// mapping id sales target amount combination
$temp = array_column($arr1, 'sales_target_amount', 'id');
foreach ($arr as $key => $value) {
$arr[$key]['sales_target_amount'] = $temp[$key]; // putting sales_target_amount for id
}
array_column — Return the values from a single column in the input array
Demo Link.
Use hashed map to group values by staff_id
<?php
$arr1 = [
[
'id' => 6,
'sales_target_amount' => '30000.00'
],
[
'id' => 10,
'sales_target_amount' => '1000.00'
]
];
$arr2 = [
[
'sales_total' => '4165.80',
'staff_id' => 6
],
[
'sales_total' => '1335.60',
'staff_id' => 10
]
];
$results = [];
foreach ($arr1 as $value) {
$results[$value['id']] = [
'sales_target_amount' => $value['sales_target_amount']
];
}
foreach ($arr2 as $value) {
$results[$value['staff_id']] = array_merge($results[$value['staff_id']], $value);
}
print_r(array_values($results));
array_merge() do not work with multidimensional array.
Try to use array_merge_recursive().
And you not need use square brackets in this context.
Run function just like
$sum = array_merge_recursive($second_array, $firs_array);
Sort answer using this library
$array = array_merge_recursive(
Arr::flattenSingle(Arr::group($array1, 'id')),
Arr::flattenSingle(Arr::group($array2, 'staff_id'))
);
What it does underneath is to first group your arrays by column you want them merged by. Then because every element in group will have only one corresponding array (cause they are grouped by unique id) flatten those groups to build array with elements like id => array_with_that_id. And then merge those flattened groups by keys which in these case are ids.
Overall this will produce
Array (
[6] => Array (
[id] => 6
[sales_total] => 4165.8
[staff_id] => 6
[sales_target_amount] => 30000
)
[10] => Array (
[id] => 10
[sales_total] => 1335.6
[staff_id] => 10
[sales_target_amount] => 1000
)
)

Remove only Key from Multidimensional Associative Array in PHP

I want to remove only key from multidimensional associative array preserving its value in PHP.
I've tried with foreach loop.
foreach($collections as $k=>$v){
foreach($v as $k1=>$v1){
foreach($v1 as $k2=>$v2){
if($k2 == 'attr_id'){
unset($collections[$k][$k1][$k2]);
}
}
}
}
I've an array like below:
$collections = [
0 => [
0 => [
"attr_id" => 23,
"value" => "Single Side"
],
1 => [
"attr_id" => 23,
"value" => "Double Side"
],
],
1 => [
0 => [
"attr_id" => 31,
"value" => "A4"
],
1 => [
"attr_id" => 31,
"value" => "12x18"
],
2 => [
"attr_id" => 31,
"value" => "B5"
],
3 => [
"attr_id" => 31,
"value" => "A5"
]
]
];
And I want output Like this:
$collections = [
23 => [ "Single Side", "Double Side" ],
31 => [ "A4", "12x18", "B5", "A5" ]
];
Please Help!
Short solution:
$expected = [];
foreach ($collections as $collection) {
$expected[$collection[0]['attr_id']] = array_column($collection, 'value');
}
You can do this with simply using two foreach() loop and push the value to attr_id
$expected = [];
foreach($collections as $k=>$v){
foreach($v as $k1=>$v1){
$expected[$v1['attr_id']][] = $v1['value'];
}
}
print_r($expected);
Output:
Array (
[23] => Array (
[0] => Single Side
[1] => Double Side
)
[31] => Array (
[0] => A4
[1] => 12x18
[2] => B5
[3] => A5
)
)
DEMO: https://3v4l.org/JlsIl
Do with array_values and array_reduce
first merge all subArray's to one array
The use reduce to apppend value based with attr_id matching
Sandbox demo
$res = call_user_func_array('array_merge',array_values($arr));
$res = array_reduce($res,function($a,$b){
$a[$b['attr_id']] = isset($a[$b['attr_id']]) ? $a[$b['attr_id']] : [] ;
array_push($a[$b['attr_id']],$b['value']);
return $a;
},[]);
print_r($res);

Append two arrays having same key inside one array differently

I have two array in php likes this :
$a = [ 1 => [ 0 => 10, 1 => 1 ] ] and $b = [ 1 => [ 0 => 15, 1 => 3 ] ]
I have to make a union of these two arrays that resultant array should be like this :
$r = [ 1 => [ 0 => 10, 1 => 1 ], 1 => [ 0 => 15, 1 => 3 ] ]
Please give me idea how can i achieve this ..
Thanks in advance !!
You can't give same array index....index is unique
$r[] = $a;
$r[] = $b;
so your array will be
$r = [ [0]=>[1 => [ 0 => 10, 1 => 1 ]], [1] =>[1 => [ 0 => 15, 1 => 3 ] ]]
You can't have an array with the same key.
If you want to merge values of two arrays, use array_merge:
$a = array(
0 => 10,
1 => 1 ) ;
print_r($a);
echo "<br>";
$b = array(0 => 15,
1 => 3);
print_r($b);
echo "<br>";
$result = array_merge($a, $b);
print_r($result);

Multi Array Counting values of sub-arrays

I have multi-dimensional array:
$array = array(
array(
"id" => 1,
"value" => 100
),
array(
"id" => 1,
"value" => 200
),
array(
"id" => 1,
"value" => 300
),
array(
"id" => 2,
"value" => 2
),
array(
"id" => 2,
"value" => 5
),
array(
"id" => 3,
"value" => 10.50
),
);
I need to get new multi-dimensional array, like this:
$newArray = array(
array(
"id" => "1",
"sum_of_values" => 600
),
array(
"id" => 2,
"sum_of_values" => 7
),
array(
"id" => 3,
"sum_of_values" => 10.50
),
);
I mean, key [sum_of_values] should counts values in sub-arrays with the same key [id].
I've tried this:
$cnt = count($array);
$finalArray = array();
$tempArray = array();
for($i = 0; $i < $cnt; $i++){
if($array[$i]["id"] == $array[$i++]["id"]){
$search = $array[$i]["id"];
$column = "value";
$sum = array_sum(
array_map(
function($data) use ($column) {
return $data[$column];
},
array_filter(
$array,
function($data) use ($search) {
return fnmatch($search, $data["id"]);
}
)
)
);
$tempArray = array(
"id" => $array[$i]["id"],
"sum_of_values" => $sum
);
$finalArray[] = $tempArray;
} else {
$tempArray = array(
"id" => $array[$i]["id"],
"sum_of_values" => $array[$i]["value"]
);
}
}
And it works, it counts values of sub-arrays with same [id]. But the problem is not returning sub-arrays, key [id] of which doesn't have same examples. In my case - sub-array with [id] = 3 will not return. Also, sub-arrays with [id] = 1 and [id] = 2 will repeat [n-n/2] times.
I think, that problem is in using cycle - for ($i = 0; $i < $cnt; $i++) and condition if ($array[$i]["id"] == $array[$i++]["id"]), because it looks stupid, but i can't find anything else.
Your function seems too complicated. How about this?
$result = array();
foreach ($array as $item) {
if (!empty($result[$item['id']]))
$result[$item['id']]['sum_of_values'] += $item['value'];
else
$result[$item['id']] = array(
'id' => $item['id'],
'sum_of_values' => $item['value']
);
}
If you print_r($result) you get:
Array
(
[1] => Array
(
[id] => 1
[sum_of_values] => 600
)
[2] => Array
(
[id] => 2
[sum_of_values] => 7
)
[3] => Array
(
[id] => 3
[sum_of_values] => 10.5
)
)
Just as an alternative: this is a sitter for array_reduce():
$totals = array_reduce($array, function($reduction, $current){
$id = $current["id"];
if (empty($reduction[$id])){
$reduction[$id] = ["id"=>$id, "sum_of_values"=>0];
}
$reduction[$id]["sum_of_values"] += $current["value"];
return $reduction;
}, []);
I prefer this sort of approach to generic looping/processing: I think it's a bit cleaner. But mileage varies, obviously.

Categories