Hi i having difficulty to trace an multi dimensional array.
[
0 => array:7 [
"date" => "2016-01-19"
"placement_id" => 1
"requests" => 18
"revenue" => 1
],
1 => array:7 [
"date" => "2016-01-19"
"placement_id" => 1
"requests" => 2
"revenue" => 0.2
]
];
if placement_id are same i want resulted array:
1 => array:7 [
"date" => "2016-01-19"
"placement_id" => 1
"requests" => 20
"revenue" => 1.2
]
The requirement is to produce an output array that has:
Items with the same 'placement_id' having the 'requests' and revenue summed.
The key of the entry in the output array will be be the 'placement_id'.
That means that the output array will be smaller that the input array.
I decided to use the array_reduce function. There is no special reason, foreach loops work fine. It isn't any more efficient. It is just different.
The important point about array_reduce is that the $carry (accumulator) can be an array...
Working example at Eval.in
The code:
$outArray = array();
$outArray = array_reduce($src,
function($carry, $item) { // accumulate values if possible
$carryKey = $item['placement_id']; // array key
if (isset($carry[$carryKey])) { // accumulate values
$carry[$carryKey]['requests'] += $item['requests'];
$carry[$carryKey]['revenue'] += $item['revenue'];
} else { // is new - add to the output...
$carry[$carryKey] = $item;
}
return $carry;
},
array() /* accumulator ($carry) is an internal variable */);
Output Array:
array (2) [
'1' => array (4) [
'date' => string (10) "2016-01-19"
'placement_id' => integer 1
'requests' => integer 20
'revenue' => float 1.2
]
'666' => array (4) [
'date' => string (10) "2016-04-01"
'placement_id' => integer 666
'requests' => integer 266
'revenue' => float 666.20000000000005
]
]
Test Data:
$src = array(
0 => array(
"date" => "2016-01-19",
"placement_id" => 1,
"requests" => 18,
"revenue" => 1,
),
1 => array(
"date" => "2016-04-01",
"placement_id" => 666,
"requests" => 266,
"revenue" => 666.2,
),
2 => array(
"date" => "2016-01-19",
"placement_id" => 1,
"requests" => 2,
"revenue" => 0.2,
),
);
Taking that $arr parameter is the array that you show, we could create a function like this to look for duplicates ids and aggregate them. The $output array will return the results.
public function checkArray($arr) {
$output = array();
$deleted = array();
foreach($arr as $key => $value){
if (!in_array($key, $deleted)) {
$entry = array();
$entry['date'] = $value['date'];
$entry['placement_id'] = $value['placement_id'];
$entry['requests'] = $value['requests'];
$entry['revenue'] = $value['revenue'];
foreach($arr as $key2 => $value2){
if($key != $key2 && $value['placement_id'] == $value2['placement_id']){
$entry['requests'] += $value2['requests'];
$entry['revenue'] += $value2['revenue'];
$deleted[] = $key2;
}
}
$output[] = $entry;
}
}
return $output;
}
Related
[
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);
i have this array
[
[[222] => 1 [333] => 2 [444] => 0],
[[222] => 0 [333] => 2 [444] => 1],
[[222] => 1 [333] => 2 [444] => 0]
]
where [222], [333], [444] are student ids
and 0 means absent
1 means Present
2 means Leave
i want the output will
[ 'student_id' => '222'
'present' => 2 /* total present*/
'absent' => 1 /* total absent*/
'leave' => 0 /* total leave*/
],
[ 'student_id' => '333'
'present' => 0 /* total present*/
'absent' => 0 /* total absent*/
'leave' => 3 /* total leave*/
],
etc.
please give me some soluation in php code
This does exactly what you want, but this site is not a coding service, so i really think you should take the time to understand how i did, and next time try something and share it on your post:
$array = [
[
"222" => 1,
"333" => 2,
"444" => 0
],
[
"222" => 0,
"333" => 2,
"444" => 1
],
[
"222" => 1,
"333" => 2,
"444" => 0
]
];
$results = [];
foreach($array as $k=>$v){
foreach($v as $id=>$value){
if(!isset($results[$id])){
$results[$id] = [
'student_id' => $id,
'present' => 0,
'absent' => 0,
'leave' => 0
];
}
if($value == 0){
$results[$id]['absent']++;
}
if($value == 1){
$results[$id]['present']++;
}
if($value == 2){
$results[$id]['leave']++;
}
}
}
$results = array_values($results);
print_r($results);
This looks like JSON value with there respective keys. You may do that firstly you can arrange these values in PHP ARRAY using foreach then convert that array in JSON.
foreach looping is the best way to access each key/value pair from an array.
foreach($featured as $key => $value){...}
The $key => $value in the foreach loop refers to the key-value pairs in associative arrays, where the key serves as the index to determine the value instead of a number like 0,1,2,... In PHP, associative arrays look like this
$featured = array('student_id' => '111', 'present' => '2', etc.);
I have an Array Like this:
$ratesData = [
1 => [
'id' => 1,
'amount' => 2
],
0 => [
'id' => 1,
'amount' => 1
],
2 => [
'id' => 1,
'amount' => 3
],
3 => [
'id' => 2,
'amount' => 2
]
];
I want to keep the duplicated id arrays with cheapest amount, the result will be like this:
[
0 => [
'id' => 1,
'amount' => 1
],
1 => [
'id' => 2,
'amount' => 2
]
]
I have a code that works with this problem, but I'm searching an elegant way to accomplish this without all this loops:
foreach($ratesData as $firstLoopKey => $firstLoopValue) {
foreach($ratesData as $secondLoopKey => $secondLoopValue) {
if($firstLoopValue['id'] === $secondLoopValue['id'] && $firstLoopKey != $secondLoopKey ) {
if ($ratesData[$secondLoopKey]['total_amount'] > $ratesData[$firstLoopKey]['total_amount']) {
$deleteElements[] = $secondLoopKey;
}
}
}
}
if (isset($deleteElements)) {
foreach ($deleteElements as $element) {
unset($ratesData[$element]);
}
}
$ratesData = array_values($ratesData);
return $ratesData;
You can sort by amount descending and then extract the array indexing by id which will eliminate the duplicates with the lowest amount overwriting the higher:
array_multisort(array_column($ratesData, 'amount'), SORT_DESC, $ratesData);
$ratesData = array_column($ratesData, null, 'id');
Yields:
Array
(
[1] => Array
(
[id] => 1
[amount] => 1
)
[2] => Array
(
[id] => 2
[amount] => 2
)
)
I always like having the key the same as a unique id to make array access/sorting easier, but you can re-index if needed:
$ratesData = array_values($ratesData);
Some simple solution:
// your source array
$ratesData = [];
// result array
$filtered = [];
foreach ($ratesData as $v) {
$id = $v['id'];
// if this is `$id`, which is not in `$filtered` yet
// or value of `$filtered[$id]['amount']` is greater then current `$v`
// then replace `$filtered[$id]` with current `$v`
if (!isset($filtered[$id]) || $filtered[$id]['amount'] > $v['amount']) {
$filtered[$id] = $v;
}
}
echo'<pre>',print_r(array_values($filtered)),'</pre>';
Another good solution
$uniqueRates = [];
foreach ($ratesData as $rateData) {
$key = $rateData['id'];
if (!\array_key_exists($key, $uniqueRates) ||
$rateData['total_amount'] < $uniqueRates[$key]['total_amount']
) {
$uniqueRates[$key] = $rateData;
}
}
return array_values($uniqueRates);
Hello I want to convert this type of array
[
"Continent.0.name" => "Europe",
"Continent.0.value" => 25,
"Continent.1.name" => "Asia",
"Continent.1.value" => 4.17,
"Total" => 190
]
into
[
'continent' => [
'Europe' => 25
'Asia' => 4.17
],
'Total => 190
]
'name' after dot should be assigned as key and 'value' after dot shoudl be assigned as value.
Any idea?
Try this
EDIT:
<?php
$arr = [
"Continent.0.name" => "Europe",
"Continent.0.value" => 25,
"Continent.1.name" => "Asia",
"Continent.1.value" => 4.17,
"Total" => 190
];
$return = array();
$continentIndex = array();
foreach ($arr as $key => $currCell)
{
$name = explode('.', $key);
if(isset($name[2]) && $name[2] === 'name')
{
$return[$name[0]][$currCell] = array();
$continentIndex[$name[1]] = $currCell;
}
else if(isset($name[2]) && $name[2] === 'value')
$return[$name[0]][$continentIndex[$name[1]]] = $currCell;
if(!isset($name[1]))
$return[$key] = $currCell;
}
var_dump($return);
?>
return
array (size=2)
'Continent' =>
array (size=2)
'Europe' => int 25
'Asia' => float 4.17
'Total' => int 190
I have a flat associative array which may contain duplicate values.
Array (
[for-juniors] => product_category
[for-men] => product_category
[coats] => product_category
[for-women] => product_category
[7-diamonds] => brand
)
I need to restructure the data to store the original values as new keys and the original keys pushed into subarrays associated with the new keys.
array(
'product_category' => array(
'for-juniors',
'for-men',
'coats',
'for-women'
),
'brand' => array(
'7-diamonds'
)
);
$grouped = array();
foreach ($input as $choice => $group) {
$grouped[$group][] = $choice;
}
var_dump($grouped);
Because within a foreach() loop, the values are declared BEFORE the keys, you can actually populate the new data structure with a body-less foreach() loop.
Code: (Demo)
$array = [
'for-juniors' => 'product_category',
'for-men' => 'product_category',
'coats' => 'product_category',
'for-women' => 'product_category',
'7-diamonds' => 'brand'
];
$grouped = [];
foreach ($array as $grouped[$group][] => $group);
var_export($grouped);
Output:
array (
'product_category' =>
array (
0 => 'for-juniors',
1 => 'for-men',
2 => 'coats',
3 => 'for-women',
),
'brand' =>
array (
0 => '7-diamonds',
),
)
This'll do:
function array_flip_safe(array $array) : array
{
return array_reduce(array_keys($array), function ($carry, $key) use (&$array) {
$carry[$array[$key]] ??= []; // PHP 7.0 - ^7.3: $carry[$array[$key]] = $carry[$array[$key]] ?? [];
$carry[$array[$key]][] = $key;
return $carry;
}, []);
}
The callback creates an empty array if the array doesn't already exist. Then it appends current iteration's $key ($value of array_keys($array)) to that array.
Here's an example for better understanding:
$businessHours = [
'mo' => '13:00 - 16:00',
'tu' => '8:00 - 12:00',
'we' => '13:00 - 16:00',
'th' => '8:00 - 12:00',
'fr' => '13:00 - 16:00',
'sa' => '',
'su' => '',
];
$flipped = array_flip_safe($businessHours);
ray($flipped); (or var_dump, var_export, etc.) outputs:
array:3 [▼
"13:00 - 16:00" => array:3 [▼
0 => "mo"
1 => "we"
2 => "fr"
]
"8:00 - 12:00" => array:2 [▼
0 => "tu"
1 => "th"
]
"" => array:2 [▼
0 => "sa"
1 => "su"
]
]
Note that the order of inner arrays' values is the same as the order of original array's keys.