Sorting sub array values in MultiDimension Array - php

I am trying to sort an array sent from an XML feed.
The Array looks like this from print_r($answer);:
Array
(
[size] => Array
(
[0] => 1.5m x 1.5m
[1] => 1.5m x 3m
[2] => 3m x 6.0m
[3] => 3m x 2.3m
)
[rate] => Array
(
[0] => 80
[1] => 135
[2] => 295
[3] => 180
)
[sortorder] => Array
(
[0] => 3
[1] => 4
[2] => 1
[3] => 2
)
.
.
.
)
I want to get out the array:
Array
(
[size] => Array
(
[0] => 3m x 6.0
[1] => 3m x 2.3m
[2] => 1.5m x 1.5m
[3] => 1.5m x 3m
)
[rate] => Array
(
[0] => 295
[1] => 180
[2] => 80
[3] => 135
)
[sortorder] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
)
.
.
.
)
What I am trying to do is use the Sort Order sub array to display the items in that order
I have tried a number of uasort() and array_multisort() examples, but all seem to order the sub arrays and not the values inside the sub arrays
Any ideas will be a great help. Cheers

This one sorts $answer['sortorder'] and uses those keys to sort the rest of $answer without restructuring first.
// sort $answer['sortorder'] and retrieve indices.
asort($answer['sortorder']);
$idx = array_keys($answer['sortorder']);
// do sorting
$sorted = array();
foreach($answer as $key=>$subarr) {
if ($key != 'sortorder') { // don't sort
foreach($idx as $i) {
$sorted[$key][] = $subarr[$i];
}
} else {
// $answer['sortorder'] is already sorted.
$sorted[$key] = $subarr;
}
}
print_r($sorted);
See it in action here.

This approach will re-structure the array with the sort order being the index, sort the array, then return it to it's original structure.
echo '<pre>';
$array['size'][0] = '1.5m x 1.5m';
$array['size'][1] = '1.5m x 3m';
$array['size'][2] = '3m x 6.0m';
$array['size'][3] = '3m x 2.3m';
$array['rate'][0] = 80;
$array['rate'][1] = 135;
$array['rate'][2] = 295;
$array['rate'][3] = 180;
$array['sortorder'][0] = 3;
$array['sortorder'][1] = 4;
$array['sortorder'][2] = 1;
$array['sortorder'][3] = 2;
$temp = array();
foreach($array['sortorder'] as $key => $value)
{
$temp[$array['sortorder'][$key]] = array(
'size'=>$array['size'][$key],
'rate'=>$array['rate'][$key],
'sortorder'=>$array['sortorder'][$key]
);
}
ksort($temp);
$array = array();
foreach($temp as $key => $value)
{
$array['size'][] = $value['size'];
$array['rate'][] = $value['rate'];
$array['sortorder'][] = $value['sortorder'];
}
print_r($array);

May I propose to use a different array structure that bundles each size, rate and sort order into one item:
array(
array('size' => '...', 'rate' => '...', 'sort order' => '...'),
...
)
That makes it trivial to sort, and in fact easier to work with in general.
This PHP 5.3+ code does this transformation and sorting:
$answer = array_map(function ($size, $rate, $sortorder) {
return compact('size', 'rate', 'sortorder');
}, $answer);
usort($answer, function ($a, $b) { return $a['sortorder'] - $b['sortorder']; });

Related

compare values in array and delete it from array - php

array:
[0] => Array
(
[0] => A
[1] => 70H
[2] => 51.57
[3] => RH
)
[1] => Array
(
[0] => B
[1] => 70H
[2] => 39.11
[3] => RH
)
[2] => Array
(
[0] => C
[1] => 70H
[2] => 12.11
[3] => RH
)
This is just an example of an array, my real array is really big.
I want to find the same values in array like this [key][1], compare their price, find the lowest PRICE [KEY][2]and save [key][0] for all other elements, if the price is the same then random save one as lowest. In the example i give the result that i want will be:
[0] A
[1] B
I tried this code but it doesn't work for me:
$res=array();
$Mfr= arrays_column($final_array, 1);
$dupes = array_diffs(array_count_values($Mfr), array(1)); // how many times a mfr sku appears
print "\nThese are repetitive values:\n[mfrsku] => (number of reps)\n";
foreach($dupes as $key => $val){
$temp = array_intersect_key(arrays_column($final_array, 3), $key);
if(count(array_unique($temp)) < count($temp)){
$temp = array_intersect_key(arrays_column($final_array, 2), array_intersect($Mfr, array($key)));
$temp = array_diffs($temp, array(min($temp)));
$res[] = array_intersect_key(arrays_column($final_array, 0), $temp);
print_r($res);die;
}
}
You can collect during first foreach loop all minimum values and then easily collect records which have another values:
Declaring arrays
$minvals = []; // array of minimum values
$spec = []; // resultant array
$tmp = []; // tmp array (needs for similar records)
First array (collecting minimum values(prices)):
foreach($ar as $rec){
$val = $rec[2]; // price
if(isset($minvals[$rec[1]] )) { // next appearance of the same $rec[1]
if ($minvals[$rec[1]] >= $val) {
$minvals[$rec[1]] = $val;
}
} else { // first appearance
$minvals[$rec[1]] = $val;
}
}
Now you can collect desired values of from the first column:
foreach($ar as $rec){
if ($rec[2] > $minvals[$rec[1]]){ // if price is bigger than minimum
$spec[] = $rec[0];
} else if($rec[2] == $minvals[$rec[1]]){ // if equal
if(isset($tmp[$rec[1]])){ // if it appears at not the first time
$spec[] = $rec[0];
} else {
$tmp[$rec[1]] = 1;
}
}
}
In case of input array like:
$ar = [ ["A","70H","51.57","RH"],
["B","70H","39.11","RH"],
["C","70H","12.11","RH"],
["A2","71H","11.57","RH"],
["B2","71H","32.11","RH"],
["C2","73H","12.11","RH"],
["C3","73H","11.11","RH"],
["C4","73H","33.11","RH"],
["C5","73H","3.11","RH"],
["C6","73H","3.11","RH"],
];
Outputs would be next:
Array
(
[0] => A
[1] => B
[2] => B2
[3] => C2
[4] => C3
[5] => C4
[6] => C6
)
Demo

php split array on change of value in column data

I am trying to split array data into multiple arrays based on change in data value at known position (column).
$input = array(
array(1,2,3),
array(4,5,3),
array(7,8,4),
array(9,10,4),
array(11,12,4)
);
Here column 3 changes values from 3 to 4
and expected result is to have 2 arrays
$out1 = array(array(1,2,3),array(4,5,3));
$out2 = array(array(7,8,4), array(9,10,4), array(11,12,4));
since number of rows are variable, cannot use array_chunk
since column 3 values are variable, cannot use array_filter
number of output arrays are also variable.
trying splice but failing...
You can use array_reduce to make new array, where index will be equal to last numbers in items
$new = array_reduce($input, function($c, $x) { $c[$x[2]][] = $x; return $c; }, [] );
$out1 = $new[3];
$out2 = $new[4];
demo
But if array is not sorted and you want to split at points of changing that number, the code can be
$i = -1;
$last = null;
$new = [];
foreach($input as $x) {
if ($x[2] != $last) {
$i++;
$last = $x[2];
}
$new[$i][] = $x;
}
demo
You can use split index with index of array,
$out1 = $out2 = [];
$splitIndex = 2;
foreach($input as $k => $v){
if($k < $splitIndex){
$out1[] = $v;
}else{
$out2[] = $v;
}
}
print_r($out1);
print_r($out2);
Working demo
Output:-
Array
(
[0] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
[1] => Array
(
[0] => 4
[1] => 5
[2] => 3
)
)
Array
(
[0] => Array
(
[0] => 7
[1] => 8
[2] => 4
)
[1] => Array
(
[0] => 9
[1] => 10
[2] => 4
)
[2] => Array
(
[0] => 11
[1] => 12
[2] => 4
)
)

Multiply two arrays values based on the values on the other values

From the following array I am trying to multiple the quantity and the price on the condition that itemType is Zo.
(
[customer] => 4
[itemNo] => Array
(
[0] => 1
[1] => 2
)
[itemName] => Array
(
[0] => Type A
[1] => Type B
)
[itemType] => Array
(
[0] => Zo
[1] => Ram
)
[quantity] => Array
(
[0] => 2
[1] => 3
)
[price] => Array
(
[0] => 500
[1] => 2000
)
)
Here is what I have tried so far but with no success.
$lq = 0;
$total =0;
for ($i=0;$i<count($_REQUEST['price']);$i++) {
if(in_array("Ram", $_REQUEST['itemType'])){
$total += $_REQUEST['price'][$i] * $_REQUEST['quantity'][$i];
}else{
$lq += $_REQUEST['quantity'][$i];
}
}
echo ($total).'<br>';
echo ($lq);
My expected output is:
$total = 1000;//Quantity x Price
$lq = 3//Quantity only
You're not checking itemType of the same item that you're adding to the total. You're just checking whether any of the items have that itemType. You're also looking for Ram, not Zo.
if ($_REQUEST['itemType'][$i] == 'Zo') {
$total += $_REQUEST['price'][$i] * $_REQUEST['quantity'][$i];
} else {
$lq += $_REQUEST['quantity'][$i];
}
Try:
$data = $_REQUEST;
$key = array_search('Zo',$data['itemType']);
$total = $data['quantity'][$key] * $data['price'][$key];//Zo price*qty
$lq = array_sum($data['quantity']) - $data['quantity'][$key];//non-Zo qty
Live demo

Comparing in an Array: If two highest value exists, then compare the other value

Suppose I have an array like:
array( [0] => array([item]=>apple [buy]=>50 [sell]=>30)
[1] => array([item]=>lemon [buy]=>50 [sell]=>60)
[2] => array([item]=>banana [buy]=>40 [sell]=>20)
[3] => array([item]=>orange [buy]=>20 [sell]=>30)
)
Currently I am using this script to check which item has the most buyer
function getMax($array, $val)
{
$max = 0;
foreach( $array as $k => $v )
{
$max = max( array( $max, $v[$val] ) );
}
return $max;
}
$highestBuy = getMax($thisArray, 'buy');
foreach($thisArray as $i=>element){
if($element['buy'] == $highestBuy){
$thisArray[$i]['highestBuy'] = 'yes';
} else {
$thisArray[$i]['highestBuy'] = 'no';
}
}
In this case, both apple and lemon will have highestBuy a yes value. But now I want to find out which item is the most popular by checking their sell if there are two or more same value of highestBuy. Which is the most simple or fastest way to make the output like:
array([0] => array([item]=>apple [buy]=>50 [sell]=>30 [mostPopular]=>no)
[1] => array([item]=>lemon [buy]=>50 [sell]=>60 [mostPopular]=>yes)
[2] => array([item]=>banana [buy]=>40 [sell]=>20 [mostPopular]=>no)
[3] => array([item]=>orange [buy]=>20 [sell]=>30 [mostPopular]=>no)
)
Thanks in advance.
EDIT:
What I want to do is:
find out the highest buy
If this value occur only once(which means there are one highest buy in the array) then push the [mostPouplar]=>yes into the array
If not(there are two or more same highest value), then find out the highest sell.
That's mean if the highest value is unique, it will stop doing further action. If not, it will keep going to find secondary highest value in an array. Is it possible to achieve this?
Sort array with your rules and take first element
$array = array( '0' => array('item'=>apple, 'buy'=>50 ,'sell'=>30),
'1' => array('item'=>lemon, 'buy'=>50, 'sell'=>60),
'2' => array('item'=>banana, 'buy'=>40, 'sell'=>20),
'3' => array('item'=>orange, 'buy'=>20 ,'sell'=>30)
);
usort($array,
function($a, $b) {
$res = $b['buy'] - $a['buy'];
if (!$res) $res = $b['sell'] - $a['sell'];
return $res; });
result:
Array (
[0] => Array ( [item] => lemon [buy] => 50 [sell] => 60 )
[1] => Array ( [item] => apple [buy] => 50 [sell] => 30 )
[2] => Array ( [item] => banana [buy] => 40 [sell] => 20 )
[3] => Array ( [item] => orange [buy] => 20 [sell] => 30 ) )
I had changed the getMax() to return the index of the most popular item
function getMax($array, $val, $val2)
{
$max_item = 0;
foreach( $array as $k => $v )
{
if($array[$max_item][$val] <= $v[$val] && $array[$max_item][$val2] <= $v[$val2])
$max_item = $k;
}
return $max_item;
}
$highestBuy = getMax($thisArray, 'buy', 'sell');
foreach($thisArray as $i => $element){
$thisArray[$i]['mostPopular'] = ($i == $highestBuy) ? 'yes' : 'no';
}

Filling php array that has missing values

I've a series of arrays with values that goes from 1 to 5. Almost every array has missing values, some even dont have any values. My objective is to fill the missing values with 0. All those arrays are stored into a multidimensional array.
My array looks like:
Array
(
[1] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
[2] => Array
(
[0] => 1
[1] => 5
)
[3] => Array
(
[0] => (this array has no values)
)
[4] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
)
etc...
)
How it should be:
Array
(
[1] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 0
[4] => 0
)
[2] => Array
(
[0] => 1
[1] => 0
[2] => 0
[3] => 0
[4] => 5
)
[3] => Array
(
[0] => 0
[1] => 0
[2] => 0
[3] => 0
[4] => 0
)
[4] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
)
etc...
)
Any help would be appriciated!
For each of your subarrays loop through the numbers 1 to 5, and if that value exists set its key to be one less than its value:
$newarray = array();
foreach($arr as $key => $subarr) {
for ($i = 1; $i <= 5; $i++) {
if (in_array($i, $subarr)) $newarray[$key][$i - 1] = $i;
else $newarray[$key][$i - 1] = 0;
}
}
Where $newarray is your output and $arr is your input array.
You may want to note that PHP does not truly do multidimensional arrays. It only allows you to relate 2 flat arrays together which is not true multidimensionality.
This does not work and will produce results described above.
$menu[1] = "My Training"; //not $menu[1][0]
$menu[1][1] = "To Do List";
$menu[1][2] = "Catalog";
$menu[1][3] = "Self-Report";
$menu[1][4] = "Completions";
$menu[2] = "Manager";
$menu[2][1] = "Direct Reports";
$menu[2][2] = "Incompletes";
$menu[2][3] = "Completions";
$menu[3] = "Instructor";
$menu[3][1] = "My Classes";
$menu[3][2] = "Printables";
$menu[3][3] = "Qualifications";
This does work.
$menu[1] = "My Training"; //not $menu[1][0]
$submenu[1][1] = "To Do List";
$submenu[1][2] = "Catalog";
$submenu[1][3] = "Self-Report";
$submenu[1][4] = "Completions";
$menu[2] = "Manager";
$submenu[2][1] = "Direct Reports";
$submenu[2][2] = "Incompletes";
$submenu[2][3] = "Completions";
$menu[3] = "Instructor";
$submenu[3][1] = "My Classes";
$submenu[3][2] = "Printables";
$submenu[3][3] = "Qualifications";
$submenu is only related to $menu through the first key number as there are no first dimension values to $submenu.
Something like this (array_pad() won't do the trick). $myArray is your source array. Completed array is returned in $result:
$result = array();
foreach( $myArray as $subKey=>$subArray ) {
for( $i=0; $i<5; $i++ ) {
if( isset( $subArray[$i] )) {
$result[$subKey][$i] = $subArray[$i];
} else {
$result[$subKey][$i] = 0;
}
}
}
Note, we do copy of the array. You cannot fill array in-place.
It's been many years since I wrote any PHP but something like this might do the trick I guess?
for($i = 0; $i < 5; $i++)
{
if(empty($myArray[$i])
{
$myArray[$i] = 0;
}
}

Categories