I will try to explain my problem in small examples:
I have a multidimensional array that represents data from the database, lets's say the input looks like this:
Array
(
[0] => Array
(
[groupRange] => 20-25
[value] => 12
[followersFemaleRate] => 12
[followersMaleRate] => 14
)
[1] => Array
(
[groupRange] => 30-44
[value] => 32
[followersFemaleRate] => 17
[followersMaleRate] => 3
)
[2] => Array
(
[groupRange] => 30-44
[value] => 88
[followersFemaleRate] => 17
[followersMaleRate] => 3
)
)
What I want? To sum value, followersFemaleRate, followersMaleRate with the same groupRange, so the output should be this:
Array
(
[0] => Array
(
[groupRange] => 20-25
[value] => 12
[followersFemaleRate] => 12
[followersMaleRate] => 14
)
[1] => Array
(
[groupRange] => 30-44
[value] => 120
[followersFemaleRate] => 34
[followersMaleRate] => 6
)
)
My code:
$RangeArray = [];
foreach($dbProfile->getData() as $d) {
foreach ($d->getGroupPercentages() as $x){
$ageRangeSingleArray['groupRange'] = $x->getGroupRange();
$ageRangeSingleArray['value'] = $x->getValue();
$ageRangeSingleArray['followersFemaleRate'] = $x->getFollowerGenderFemale();
$ageRangeSingleArray['followersMaleRate'] = $x->getFollowerGenderMale();
$RangeArray [] = $ageRangeSingleArray;
}
}
However im stuck, my idea is to first check if groupRage already exists, if yes, sum values for that range, if not add new element groupRange with values, any help with code?
#Salines solution was good, but I offer a simple solution for the beginners...
Another simple solution to your problem:
$input = [
[
'groupRange' => '20-25',
'value' => 12,
'followersFemaleRate' => 12,
'followersMaleRate' => 14,
],
[
'groupRange' => '30-44',
'value' => 88,
'followersFemaleRate' => 17,
'followersMaleRate' => 3,
],
[
'groupRange' => '30-44',
'value' => 32,
'followersFemaleRate' => 17,
'followersMaleRate' => 3,
],
];
$groupRangeHolder = [];
$output = [];
foreach($input as $item) {
if( ! array_key_exists( $item['groupRange'] , $groupRangeHolder ) )
{
$groupRangeHolder[$item['groupRange']]['value'] = $item['value'];
$groupRangeHolder[$item['groupRange']]['followersFemaleRate'] = $item['followersFemaleRate'];
$groupRangeHolder[$item['groupRange']]['followersMaleRate'] = $item['followersMaleRate'];
}
else
{
$groupRangeHolder[$item['groupRange']]['value'] += $item['value'];
$groupRangeHolder[$item['groupRange']]['followersFemaleRate'] += $item['followersFemaleRate'];
$groupRangeHolder[$item['groupRange']]['followersMaleRate'] += $item['followersMaleRate'];
}
}
$cur = 0;
foreach($groupRangeHolder as $key => $values)
{
$output[$cur]['groupRange'] = $key;
$output[$cur]['value'] = $values['value'];
$output[$cur]['followersFemaleRate'] = $values['followersFemaleRate'];
$output[$cur++]['followersMaleRate'] = $values['followersMaleRate'];
}
echo "<pre>";
print_r($output);
echo "</pre>";
try:
$input = [
[
'groupRange' => '20-25',
'value' => 12,
'followersFemaleRate' => 12,
'followersMaleRate' => 14,
],
[
'groupRange' => '30-44',
'value' => 88,
'followersFemaleRate' => 17,
'followersMaleRate' => 3,
],
[
'groupRange' => '30-44',
'value' => 32,
'followersFemaleRate' => 17,
'followersMaleRate' => 3,
],
];
$groupedArray = [];
foreach( $input as $item ){
$groupedArray[$item['groupRange']]['groupRange'] = $item['groupRange'];
$groupedArray[$item['groupRange']]['value'] = ($groupedArray[$item['groupRange']]['value'] ?? 0) + $item['value'];
$groupedArray[$item['groupRange']]['followersFemaleRate'] = $item['followersFemaleRate'];
$groupedArray[$item['groupRange']]['followersMaleRate'] = $item['followersMaleRate'];
}
$output = array_values($groupedArray);
print_r($output);
output:
Array
(
[0] => Array
(
[groupRange] => 20-25
[value] => 12
[followersFemaleRate] => 12
[followersMaleRate] => 14
)
[1] => Array
(
[groupRange] => 30-44
[value] => 120
[followersFemaleRate] => 17
[followersMaleRate] => 3
)
)
Related
For instance :
Array
(
[0] => Array
(
[id] => 23
[merchant_id] => 23
)
[1] => Array
(
[id] => 24
[merchant_id] => 46
)
)
I want to delete the list which merchant_id except 46, after the operation:
Array
(
[0] => Array
(
[id] => 24
[merchant_id] => 46
)
)
how the best way to removing this array list?
You can get result using array_filter as follows
// suppose your data is in $data variable
$data = [
['id' => 23,
'merchant_id' => 23],
['id' => 23,
'merchant_id' => 46],
];
//return true only if marchant_id == 46
$filtered_array = array_filter($data,function($datum){
return $datum["merchant_id"] == 46;
});
Hi Please check below code
$array = array(
array('id' => 23, 'merchant_id' => 23),
array('id' => 24, 'merchant_id' => 46),
array('id' => 25, 'merchant_id' => 34),
array('id' => 26, 'merchant_id' => 46),
);
$final = array();
foreach ($array as $key => $value) {
if($value['merchant_id'] == 46){
$final[] = $value;
}
}
print_r($final);
If you are struggling with the array functions a simple foreach loop and a test of the field you are interested in would do nicely
$A = [ ['id' => 23, 'merchant_id' => 23 ],
['id' => 24, 'merchant_id' => 46 ],
['id' => 25, 'merchant_id' => 21 ],
['id' => 26, 'merchant_id' => 29 ],
];
foreach ( $A as $key => $t ) {
if( $t['merchant_id'] != 46 ){
unset($A[$key]);
}
}
print_r($A);
RESULT
Array
(
[1] => Array
(
[id] => 24
[merchant_id] => 46
)
)
Guys I want to sum two array fields liked_cnt , coupon_cnt if first field id is same
how can I do this?
I did this but its toooooo slow
if (end($like)['id'] > end($coupon)['id']) {
$i = end($like)['id'];
$j = end($coupon)['id'];
}else {
$i = end($coupon)['id'];
$j = end($like)['id'];
}
for ($k=0; $k <= $i; $k++) {
for ($l=0; $l < $j; $l++) {
if ($like['id'] == $coupon['id']) {
$score[$like['id']] = ($coupon['coupon_cnt'] * 1000) + $like['liked_cnt'];
}else {
$score[$i] = 0;
}
}
}
//first array $Like
Array ( [0] => Array ( [id] => 85 [liked_cnt] => 6 ) [1] => Array ( [id] => 86 [liked_cnt] => 14 ) [2] => Array ( [id] => 92 [liked_cnt] => 6 ) [3] => Array ( [id] => 93 [liked_cnt] => 6 )
//second array $coupon
Array ( [0] => Array ( [id] => 35 [coupon_cnt] => 2 ) [1] => Array ( [id] => 86 [coupon_cnt] => 1 ) [2] => Array ( [id] => 139 [coupon_cnt] => 1 ) )
There is no magic algorithm builtin to php that can really compute your desired result in a much more efficient way. This might be slightly more efficient, but most of all it is more readable:
<?php
$input = [
[
['id' => 85, 'liked_cnt' => 6],
['id' => 86, 'liked_cnt' => 14],
['id' => 92, 'liked_cnt' => 6],
['id' => 93, 'liked_cnt' => 6]
],
[
['id' => 35, 'coupon_cnt' => 2],
['id' => 86, 'coupon_cnt' => 1],
['id' => 139, 'coupon_cnt' => 1]
]
];
$output = [];
foreach ($input as $set) {
array_walk($set, function($entry) use (&$output) {
$count = array_pop($entry);
$id = array_pop($entry);
if (array_key_exists($id, $output)) {
$output[$id]['total_cnt'] += $count;
} else {
$output[$id] = ['id' => $id, 'total_cnt' => $count];
}
});
}
print_r(array_values($output));
The output obviously is:
Array
(
[0] => Array
(
[id] => 85
[total_cnt] => 6
)
[1] => Array
(
[id] => 86
[total_cnt] => 15
)
[2] => Array
(
[id] => 92
[total_cnt] => 6
)
[3] => Array
(
[id] => 93
[total_cnt] => 6
)
[4] => Array
(
[id] => 35
[total_cnt] => 2
)
[5] => Array
(
[id] => 139
[total_cnt] => 1
)
)
UPDATE:
Considering your third comment below I add this modified version introducing the general multiplication of the coupon_cnt attribute by a factor 1000:
<?php
$input = [
[
['id' => 85, 'liked_cnt' => 6],
['id' => 86, 'liked_cnt' => 14],
['id' => 92, 'liked_cnt' => 6],
['id' => 93, 'liked_cnt' => 6]
],
[
['id' => 35, 'coupon_cnt' => 2],
['id' => 86, 'coupon_cnt' => 1],
['id' => 139, 'coupon_cnt' => 1],
['id' => 99, 'coupon_cnt' => 99]
]
];
$output = [];
foreach ($input as $set) {
array_walk($set, function($entry) use (&$output) {
$count = array_key_exists('coupon_cnt', $entry)
? 1000 * array_pop($entry)
: array_pop($entry);
$id = array_pop($entry);
if (array_key_exists($id, $output)) {
$output[$id]['total_cnt'] += $count;
} else {
$output[$id] = ['id' => $id, 'total_cnt' => $count];
}
});
}
print_r(array_values($output));
This is my array:
Array (
[0] => Array ( [SocketID] => 1 [SocketName] => Name [SocketDecimal] => 0 [SocketHex] => 00 [SocketAtt] => 1 [Category] => 1 [Value] => 100 [Procentage] => 0 )
[1] => Array ( [SocketID] => 2 [SocketName] => Name2 [SocketDecimal] => 50 [SocketHex] => 32 [SocketAtt] => 1 [Category] => 1 [Value] => 800 [Procentage] => 0 )
[2] => Array ( [SocketID] => 3 [SocketName] => Name3 [SocketDecimal] => 100 [SocketHex] => 64 [SocketAtt] => 1 [Category] => 1 [Value] => 60 [Procentage] => 0 )
)
How can I extract a row by SocketDecimal?
For example: I want to extract row where SocketDecimal = 50 and make new an array only with that row.
foreach($array as $entry) {
if($entry['SocketDecimal'] == 50)
$newArr[] = $entry;
}
$newArr will contain the desired "row". Of course you can manipulate the if-statement depending on which "row" (I'd just call it array entry) you want to extract.
It's not the best way for big data! It's easy for deep multiarrays.
$arr = array(
array('socket_id'=>1,'name'=>'test1'),
array('socket_id'=>2,'name'=>'test2'),
array('socket_id'=>3,'name'=>'test3'),
array('socket_id'=>2,'name'=>'test4')
);
$newArr = array();
foreach($arr as $row){
foreach($row as $key=>$r){
if($key == 'socket_id' && $r==2)
$newArr[] = $row;
}
}
print_r($newArr);
$result = array();
foreach($input as $i){
if($i['SocketDecimal']==50)
$result[]=$i;
}
You can do it by this method
foreach ($yourarray as $key => $value){
$newarray = array("SocketDecimal"=>$value["SocketDecimal"];
}
print_r($newarray);
If your result array is like given below
$arr = array(
array( 'SocketID' => 1, 'SocketName' => 'Name', 'SocketDecimal' => 0, 'SocketHex' => 0, 'SocketAtt' => 1, 'Category' => 1, 'Value' => 100, 'Procentage' => 0 ),
array ( 'SocketID' => 2, 'SocketName' => 'Name2', 'SocketDecimal' => 50, 'SocketHex' => 32, 'SocketAtt' => 1, 'Category' => 1, 'Value' => 800, 'Procentage' => 0 ),
array ( 'SocketID' => 3, 'SocketName' => 'Name3', 'SocketDecimal' => 100, 'SocketHex' => 64, 'SocketAtt' => 1, 'Category' => 1, 'Value' => 60, 'Procentage' => 0 )
);
print_r($arr);
Get row for SocketDecimal=50 by following loop:
<pre>
$resultArr = '';
foreach($arr as $recordSet)
{
if($recordSet['SocketDecimal'] == 50)
{
$resultArr[] = $recordSet;
break;
}
}
</pre>
print_r($resultArr);
break foreach loop so that it will not traverse for all the array when SocketDecimal(50) founded.
You can use array_column + array_search combo
$array = Array (
"0" => Array ( "SocketID" => 1, "SocketName" => "Name", "SocketDecimal" => 0, "SocketHex" => 00, "SocketAtt" => 1, "Category" => 1, "Value" => 100, "Procentage" => 0 ) ,
"1" => Array ( "SocketID" => 2, "SocketName" => "Name2", "SocketDecimal" => 50, "SocketHex" => 32, "SocketAtt" => 1, "Category" => 1, "Value" => 800, "Procentage" => 0 ),
"2" => Array ( "SocketID" => 3, "SocketName" => "Name3", "SocketDecimal" => 100, "SocketHex" => 64, "SocketAtt" => 1, "Category" => 1, "Value" => 60 ,"Procentage" => 0 )
);
var_dump($array[array_search(50,array_column($array,'SocketDecimal'))]);
I have this array:
Array (
[0] => Array (
[TaxeName] => TPS
[TaxeAmount] => 7
[Price] => 14
)
[1] => Array (
[TaxeName] => TVQ
[TaxeAmount] => 9.975
[Price] => 10
)
[2] => Array (
[TaxeName] => TVQ
[TaxeAmount] => 9.975
[Price] => 18
)
)
How I can get another array:
- Grouping the TaxeName and the TaxeAmount and
- Making the sum of the amount Price ?
Like this:
Array (
[0] => Array (
[TaxeName] => TPS
[TaxeAmount] => 7
[Price] => 14
)
[1] => Array (
[TaxeName] => TVQ
[TaxeAmount] => 9.975
[Price] => 28
)
)
It can be done with a nested foreach:
$original = array(.......); // your current array
$newArr = array();
foreach($original as $origVal){
$exists = false;
foreach($newArr as $key => $newVal){
if($newVal['TaxeName'] == $origVal['TaxeName']){
$newArr[$key]['Price'] += $origVal['Price'];
$exists = true;
break;
}
}
if(!$exists){
$newArr[] = $origVal;
}
}
Outputs
Array
(
[0] => Array
(
[TaxeName] => TPS
[TaxeAmount] => 7
[Price] => 14
)
[1] => Array
(
[TaxeName] => TVQ
[TaxeAmount] => 9.975
[Price] => 28
)
)
Something like this maybe:
$final = array();
foreach ($arr as $subarr)
{
if (!isset($final[$subarr['TaxeName']]))
{
$final[$subarr['TaxeName']] = array('Price' => 0);
}
$final[$subarr['TaxeName']]['TaxeName'] = $subarr['TaxeAmount'];
$final[$subarr['TaxeName']]['TaxeName'] = $subarr['TaxeName'];
$final[$subarr['TaxeName']]['Price'] = $final[$subarr['TaxeName']]['Price'] + $subarr['Price'];
}
The idea is to make a new array with the values that you need and initializing it with the price set to 0 so you can increment it in the foreach
You can do it like this also:
<?php
// Source
$myData = array(
array(
'TaxeName' => 'TPS',
'TaxeAmount' => 7,
'Price' => 14,
),
array(
'TaxeName' => 'TVQ',
'TaxeAmount' => 9.975,
'Price' => 10,
),
array(
'TaxeName' => 'TVQ',
'TaxeAmount' => 9.975,
'Price' => 18,
)
);
// Helper Function
function parseData($data)
{
$parsedData = array();
if (is_array($data)) {
foreach ($data as $dataItem) {
if (!array_key_exists($dataItem['TaxeName'], $parsedData)) {
$parsedData[$dataItem['TaxeName']] = array(
'TaxeName' => $dataItem['TaxeName'],
'TaxeAmount' => $dataItem['TaxeAmount'],
'Price' => floatval($dataItem['Price'])
);
} else {
$parsedData[$dataItem['TaxeName']]['Price'] += floatval($dataItem['Price']);
}
}
}
return array_values($parsedData);
}
// Test
$parsed_data = parseData($myData);
var_dump($parsed_data);
?>
Outputs:
Just use this function, input is your array, output is the array you required:
function calculate(array $input){
$output = [];
foreach ($input as $v){
if (array_key_exists($v['TaxeName'], $output)){
$output[$v['TaxeName']]['Price'] += $v['Price'];
} else {
$output[$v['TaxeName']] = $v;
}
}
return array_values($output);
}
I know that solutions with external classes are not welcome here on SO. I'm showing this just to illustrate the "Grouping the TaxeName and the TaxeAmount" task.
//use class tablearray from https://github.com/jspit-de/tableArray
$data = [
['TaxeName' => 'TPS', 'TaxeAmount' => 7, 'Price' => 14],
['TaxeName' => 'TVQ', 'TaxeAmount' => 9.975, 'Price' => 10],
['TaxeName' => 'TVQ', 'TaxeAmount' => 9.975, 'Price' => 18],
['TaxeName' => 'TVQ', 'TaxeAmount' => 19.975, 'Price' => 23]
];
$newData = tableArray::create($data)
->filterGroupSum('Price',['TaxeName','TaxeAmount'])
->fetchAll()
;
echo '<pre>';
var_export($newData);
Output:
array (
0 =>
array (
'TaxeName' => 'TPS',
'TaxeAmount' => 7,
'Price' => 14,
),
1 =>
array (
'TaxeName' => 'TVQ',
'TaxeAmount' => 9.975,
'Price' => 28,
),
2 =>
array (
'TaxeName' => 'TVQ',
'TaxeAmount' => 19.975,
'Price' => 23,
),
)
I have the following array:
Array
(
[0] => Array
(
[Vendor_ID] => 1
[Quantity] => 55
)
[1] => Array
(
[Vendor_ID] => 1
[Quantity] => 55
)
[2] => Array
(
[Vendor_ID] => 1
[Quantity] => 55
)
[3] => Array
(
[Vendor_ID] => 3
[Quantity] =>
)
[4] => Array
(
[Vendor_ID] => 3
[Quantity] =>
)
[5] => Array
(
[Vendor_ID] => 3
[Quantity] =>
)
[6] => Array
(
[Vendor_ID] => 4
[Quantity] =>
)
[7] => Array
(
[Vendor_ID] => 4
[Quantity] =>
)
[8] => Array
(
[Vendor_ID] => 4
[Quantity] =>
)
)
Which is being created with the following code:
$Display_Arr = array();
$Tick = 0;
foreach ($_POST['product'] AS $_1){
if (!in_array($_1['vendor_id'], $Display_Arr)){
$Display_Arr[$Tick] = array(
"Vendor_ID" => $_1['vendor_id'],
"Quantity" => ""
);
$Display_Arr[$Tick]["Quantity"] .= $_1['quantity'];
}else{
$Display_Arr[$Tick]["Quantity"] .= $_1['quantity'];
}
++$Tick;
}
echo "<pre>";
print_r($Display_Arr);
echo "</pre>";
But I am not getting my desired output, which is:
Array
(
[0] => Array
(
[Vendor_ID] => 1
[Quantity] => 55,55,55
)
[1] => Array
(
[Vendor_ID] => 3
[Quantity] =>
)
[2] => Array
(
[Vendor_ID] => 4
[Quantity] =>
)
)
Where am I going wrong with this?
#mathielo
The current output is:
Array
(
[1] => Array
(
[Vendor_ID] => 1
[Quantity] => 55
)
[3] => Array
(
[Vendor_ID] => 3
[Quantity] =>
)
[4] => Array
(
[Vendor_ID] => 4
[Quantity] =>
)
)
Whereas, i'm trying to obtain:
[0] => Array
(
[Vendor_ID] => 1
[Quantity] => 55,55,55
)
If I got it right, what you need is this:
EDIT: Just made some tests and got it right this time:
$Display_Arr = array();
foreach ($_POST['product'] AS $_1){
if (!array_key_exists($_1['Vendor_ID'], $Display_Arr)){
$Display_Arr[$_1['Vendor_ID']] = array(
"Vendor_ID" => $_1['Vendor_ID'],
"Quantity" => $_1['Quantity']
);
}else{
if(!empty($_1['Quantity']))
$Display_Arr[$_1['Vendor_ID']]["Quantity"] .= ",{$_1['Quantity']}";
}
}
echo "<pre>";
print_r($Display_Arr);
echo "</pre>";
The main problem was in if (!in_array($_1['vendor_id'], $Display_Arr)). PHP's in_array() checks for given needle in the array values, and we were trying to match to the Vendor_ID value stored in the outer array keys. That was fixed using array_key_exists().
EDIT 2: I used this for test data:
$_POST['product'] = array(
0 => array(
'Vendor_ID' => 1,
'Quantity' => 55
),
1 => array(
'Vendor_ID' => 1,
'Quantity' => 55
),
2 => array(
'Vendor_ID' => 1,
'Quantity' => 55
)
,
3 => array(
'Vendor_ID' => 3,
'Quantity' => ''
),
4 => array(
'Vendor_ID' => 3,
'Quantity' => ''
),
5 => array(
'Vendor_ID' => 3,
'Quantity' => ''
),
6 => array(
'Vendor_ID' => 4,
'Quantity' => ''
),
7 => array(
'Vendor_ID' => 4,
'Quantity' => ''
),
8 => array(
'Vendor_ID' => 4,
'Quantity' => ''
)
);
You won't be needing $Tick anymore, as you could use Vendor_ID as keys for the outer array.
Looks like the easiest way to solve this would be to first aggregate the vendor quantities, and then build the final array with the keys that you are using.
I am assuming the input looks something like this:
$_POST['product'] = [
['vendor_id' => 1, 'quantity' => 55],
['vendor_id' => 1, 'quantity' => 55],
['vendor_id' => 1, 'quantity' => 55],
['vendor_id' => 3, 'quantity' => null],
['vendor_id' => 3, 'quantity' => null],
['vendor_id' => 3, 'quantity' => null],
['vendor_id' => 4, 'quantity' => null],
['vendor_id' => 4, 'quantity' => null],
['vendor_id' => 4, 'quantity' => null],
];
Aggregating the quantities:
$aggregates = [];
foreach ($_POST['product'] as $product) {
$id = $product['vendor_id'];
if ( ! isset($aggregates[$id])) {
$aggregates[$id] = [];
}
if ($product['quantity'] > 0) {
$aggregates[$id][] = $product['quantity'];
}
}
The aggregates array should now look like this:
$aggregates = [
1 => [
0 => 55,
1 => 55,
2 => 55,
],
3 => [], // Empty
4 => [], // Empty
];
As you can see the data is now neatly organized and ready to be put into any format you want. Using the keys that you use in your question it is as simple as:
$output = [];
foreach ($aggregates as $vid => $qty) {
$quantity = implode(',', $qty);
$output[] = ['Vendor_ID' => $vid, 'Quantity' => $quantity];
}
The output should now look like this:
$output = [
['Vendor_ID' => 1, 'Quantity' => '55,55,55'],
['Vendor_ID' => 3, 'Quantity' => ''],
['Vendor_ID' => 4, 'Quantity' => ''],
];
This will output exactly what you are looking for although the output of the last answer (Sverri M. Olsen) is more useful. Here you get the quantities as a string while with Sverri's method you get an array in first place.
$Display_Arr = array();
$vendors=array();
foreach ($_POST['product'] AS $_1){
if (!in_array($_1['vendor_id'],$vendors)){
$vendors[]=$_1['vendor_id'];
$Display_Arr[sizeof($vendors)-1] = array(
"Vendor_ID" => $_1['vendor_id'],
"Quantity" => $_1['quantity']
);
}
else{
$vendorKey=array_search($_1['vendor_id'],$vendors);
$Display_Arr[$vendorKey]["Quantity"] .=(!empty($Display_Arr[$vendorKey]["Quantity"])?',':null).$_1['quantity'];
}
}