PHP - array values out and get similar values - php

I have an array like this
Array ( [item1] => pack1 [amount1] => 1 [price1] => 25 [amount2] => 1 [price2] => 45 [item3] => pack3 [amount3] => 4 [price3] => 65 [sender] => Submit )
I need to get the values item1 & item3 out of the array, then remove the item on them with a
str_replace
Then find largest number with
max
just the first part that is the toughest, any ideas?

foreach through the array, if the key contains item then get/set the values. Also check the value to see if it's greater than the previous to get the max

$a = array( "item1" => "pack1", "amount1" => 1, "price1" => 25, "amount2" => 1, "price2" => 45, "item3" => "pack3");
$b = array();
$pattern = '/item[1-9]/';
$max_index = 0;
foreach($a as $key => $value){
if(preg_match($pattern, $key, $matches, PREG_OFFSET_CAPTURE)){
$index = str_replace("item","",$key);
$b[$index] = $value;
if($index > $max_index){
$max_index = $index;
}
}
}
$max_value = $b[$max_index];
echo $max_value;

Related

sorting chapters in an 4 level array

I want to sort an existing array into 4 dimension array:
the "list" array that I have:
1 => "text1"
10 => "text10"
11 => "text11"
101 => "text101"
1011 => "text1011"
10123 => "text10123"
2 => "text2"
20 => "text20"
201 => "text201"
2011 => "text2011"
20111 => "text20111"
the array I want is one that has all the data sorted by each number (in 4 dimention) i mean that i won't have an other array in the end of $chapter[1] containing 10123 => "text10123" (this one will be in the same array as this one : 1011 => "text1011"
here is an exemple of the array i want
$chapter[1] = array(
1 => "text1", array(
10 => "text10", 11 => "text11", array(
101 => "text101", array(
1011 => "text1011", 10123 => "text10123" )
)
)
);
I guess you can use for-loop and break each number to digits (with str-split) and then add the arrays.
Consider the following example:
$arr = array(1, 11, 111, 113, 2, 21, 211, 213);
$chapter = array(); // this will be your result array
foreach($arr as $e) {
$digits = str_split($e);
$current = &$chapter;
foreach($digits as $d) {
if (!isset($current[$d]))
$current[$d] = array();
$current = &$current[$d];
}
}
Notice I used & to assign the new array to the original result one.
I know your array has missing key and not have to be sorted but I guess you can overcome it (filter and sort the array before)
Edited
After question has change this is the example code: (when key DATA is for the text you want and key CHILDREN for the next elements)
$arr = array(1 => "text1", 10 => "text10", 11 => "text11", 101 => "text101", 1011 => "text1011", 10123 => "text10123", 2 => "text2", 20 => "text20", 201 => "text201", 2011 => "text2011", 20111 => "text20111");
$chapter = array();
foreach($arr as $key => $val) {
$digits = str_split(substr($key, 0, 4)); // if 4 digits is the max depth
$current = &$chapter;
foreach($digits as $d) {
if (!isset($current["CHILDREN"][$d]))
$current["CHILDREN"][$d] = array();
$current = &$current["CHILDREN"][$d];
}
$current["DATA"] = $val;
}

fill in the multidimensional array with missing keys

I have the following multidimensional array. I had to create keys the way it looks to group them accordingly.
Array
(
[Oranges] => Array
(
[Name] => Oranges
[l.VA123] => 17
[l.MA123] => 12
[l.GA123] => 9
[l.CT123] => 5
)
[Apple] => Array
(
[Name] => Apple
[l.CA123] => 13
)
[Grapes] => Array
(
[Name] => Grapes
[l.WI123] => 8
[l.FL123] => 5
)
)
However, I need all the subarrays to have the same keys. Missing ones should be filled with a value of 0. The final array should be like below so that all subarrays have equal length.
Array
(
[Oranges] => Array
(
[Name] => Oranges
[l.VA123] => 17
[l.MA123] => 12
[l.GA123] => 9
[l.CT123] => 5
[l.CA123] => 0
[l.WI123] => 0
[l.FL123] => 0
)
[Apple] => Array
(
[Name] => Apple
[l.CA123] => 13
[l.WI123] => 0
[l.FL123] => 0
[l.VA123] => 0
[l.MA123] => 0
[l.GA123] => 0
[l.CT123] => 0
)
[Grapes] => Array
(
[Name] => Grapes
[l.WI123] => 8
[l.FL123] => 5
[l.CA123] => 0
[l.VA123] => 0
[l.MA123] => 0
[l.GA123] => 0
[l.CT123] => 0
)
)
You need a simple + operator. As from manual:
The + operator returns the right-hand array appended to the left-hand array; for keys that exist in both arrays, the elements from the left-hand array will be used, and the matching elements from the right-hand array will be ignored.
$items = Array
(
'Oranges' => Array
(
'Name' => 'Oranges',
'l.VA123' => 17,
'l.MA123' => 12,
'l.GA123' => 9,
'l.CT123' => 5,
),
'Apple' => Array
(
'Name' => 'Apple',
'l.CA123' => 13,
),
'Grapes' => Array
(
'Name' => 'Grapes',
'l.WI123' => 8,
'l.FL123' => 5,
),
);
// static keys
$keys = [
'l.VA123' => 0,
'l.MA123' => 0,
'l.GA123' => 0,
'l.CT123' => 0,
'l.CA123' => 0,
'l.WI123' => 0,
'l.FL123' => 0,
];
// keys generated from source array, tricky approach
$keys = array_fill_keys(
// here we merge all elements of `$items` into one array
// as keys are repeated - you definitely got all keys that
// can be in `$items`, `array_keys` will give you these keys
// `array_fill_keys` will create array where key is what you need
// and value is 0.
array_keys(call_user_func_array('array_merge', $items)),
0
);
// keys generated from source array, SIMPLE approach
$keys = [];
foreach ($items as $item) {
foreach ($item as $k => $v) {
if ($k != 'Name') {
$keys[$k] = 0;
}
}
}
foreach ($items as &$item) {
$item = $item + $keys;
}
print_r($items);
Probably someone can come up with something more efficient, but without a list of keys that you want, I think you'll need to take a couple of passes of the array:
<?php
$fruits = [
"Oranges"=>["Name"=>"Oranges", "l.VA123"=>17, "l.MA123"=>12, "1.GA123"=>9, "1.CT123"=>5],
"Apple"=>["Name"=>"Apple", "1.CA123"=>13],
"Grapes"=>["Name"=>"Grapes", "1.WI123"=>8, "1.FL123"=>5]
];
$keys = [];
foreach ($fruits as $fruit) {
unset($fruit["Name"]);
$keys = array_merge($keys, array_keys($fruit));
}
$keys = array_fill_keys(array_unique($keys), 0);
foreach ($fruits as &$fruit) {
$fruit = array_merge($keys, $fruit);
}
print_r($fruits);
Since all keys and default values are "known", create an associative array, use a foreach() and modify the rows by reference, and use the union-assignment (combined) operator. This will allow the original values to overwrite the default values.
Code: (Demo)
$keys = [
'l.VA123' => 0,
'l.MA123' => 0,
'l.GA123' => 0,
'l.CT123' => 0,
'l.CA123' => 0,
'l.WI123' => 0,
'l.FL123' => 0,
];
foreach ($items as &$row) {
$row += $keys;
}
var_export($items);
If you want the keys to be consistently positioned, then use array_replace() or array_merge() instead of the union assignment operator.
Code: (Demo)
foreach ($items as &$row) {
$row = array_replace($keys, $row);
}

get max and min value each column in multdimensional array php

I have a multidimensional array
$array1 = array(
0 => array(34554, 45, 4545454),
1 => array(434534, 35, 345345),
2 => array(43534, 35, 4343445),
3 => array(35534, 34, 342323)
);
Can we find the minimum and maximum value for each value? if we want to find min for first and second column, the other column is max, and the result array is
$array2 = array(
0=>34554,
1=>34,
2=>4545454
);
i've tried this to get min
$result = array(); // save result
array_walk_recursive($ary, function($v, $k) use (&$result) {
if (!isset($result[$k])) $result[$k] = $v;
elseif ($result[$k] > $v) $result[$k] = $v;
});
print_r ($result);
and tried this to get max
$result = array(); // save result
array_walk_recursive($ary, function($v, $k) use (&$result) {
if (!isset($result[$k])) $result[$k] = $v;
elseif ($result[$k] < $v) $result[$k] = $v;
});
print_r ($result);
Thank you.
try below solution:
$array1 = array(
0 => array(34554, 45, 4545454),
1 => array(434534, 35, 345345),
2 => array(43534, 35, 4343445),
3 => array(35534, 34, 342323)
);
//max values
$max_arr = array_map(function ($val) {
return max($val);
}, $array1);
print_r($max_arr);
//min values
$min_arr = array_map(function ($val) {
return min($val);
}, $array1);
print_r($min_arr);
//min and max values
$min_max_arr = array_map(function ($val) {
return array('min' => min($val), 'max' => max($val));
}, $array1);
print_r($min_max_arr);
output:
//max values
Array
(
[0] => 4545454
[1] => 434534
[2] => 4343445
[3] => 342323
)
//min values
Array
(
[0] => 45
[1] => 35
[2] => 35
[3] => 34
)
//min and max values
Array
(
[0] => Array
(
[min] => 45
[max] => 4545454
)
[1] => Array
(
[min] => 35
[max] => 434534
)
[2] => Array
(
[min] => 35
[max] => 4343445
)
[3] => Array
(
[min] => 34
[max] => 342323
)
)
I have added some more element so that you can notice how it works, I have arranged max min as key and value pair, if you will edit your question and show me what you want as output, I will update it.
<?php
$array1 = array(
0 => array(34554, 45, 4545454),
1 => array(434534, 35, 345345),
2 => array(43534, 35, 4343445),
3 => array(9355434, 34, 342323),
4 => array(35534, 34, 342323),
5 => array(8544534, 34, 342323),
6 => array(35534, 34, 342323)
);
foreach($array1 as $arr1){
$max = max($arr1);
$arr[$max] = min($arr1);
}
var_dump($arr);
output
array (size=6)
4545454 => int 45
434534 => int 35
4343445 => int 35
9355434 => int 34
342323 => int 34
8544534 => int 34

Count and remove duplicate arrays

I'm trying to count and remove duplicate arrays. To be a duplicate the entire array would have the match in keys and values with another.
Array
(
[0] => Array
(
[name] => Superman
[time] => 60
)
[1] => Array
(
[name] => Superman
[time] => 60
)
[2] => Array
(
[name] => Superman
[time] => 50
)
[3] => Array
(
[name] => Superman
[time] => 40
)
[4] => Array
(
[name] => Superman
[time] => 50
)
[5] => Array
(
[name] => Superman
[time] => 60
)
)
Into:
Array
(
[0] => Array
(
[name] => Superman
[time] => 60
[count] => 3
)
[1] => Array
(
[name] => Superman
[time] => 50
[count] => 2
)
[2] => Array
(
[name] => Superman
[time] => 40
)
)
I've come across this answer that can remove the duplicates, but I'm struggling to see how I may count them.
$input = array_map("unserialize", array_unique(array_map("serialize", $input)));
Quick and dirty, but you get exactly the data structure you asked for:
$data = array(
array("name" => "Superman", "time" => 60),
array("name" => "Superman", "time" => 60),
array("name" => "Superman", "time" => 50),
array("name" => "Superman", "time" => 40),
array("name" => "Superman", "time" => 50),
array("name" => "Superman", "time" => 60),
);
// count the occurrences
$occurrences = array();
for ($i = 0, $l = count($data); $i < $l; $i++) {
$serialized = serialize($data[$i]);
if (!isset($occurrences[$serialized])) {
$occurrences[$serialized] = 1;
}
else {
$occurrences[$serialized] = $occurrences[$serialized] + 1;
}
}
// get the wanted structure
$uniques = array();
foreach ($occurrences as $serialized => $count) {
$unserialized = unserialize($serialized);
if ($count > 1) {
$unserialized['count'] = $count;
}
$uniques[] = $unserialized;
}
print_r($uniques);
Not as compact as I would like, but it gets the job done:
function unserialize_unique_count($input, $k = 'count') {
$a = [];
foreach ($input as $d) {
$s = serialize($d);
$a[$s] = (isset($a[$s]) ? ($a[$s] + 1) : 1);
}
foreach ($a as $s => $c) {
$a[$s] = unserialize($s) + [ $k => $c ];
}
return array_values($a);
}
$grouped_with_count = unserialize_unique_count($input);
How it works: The first loop serializes and counts. The second unique merges. O(n).
How to use: Pass your multi-dimensional array as argument #1. Gives you back uniques with an additional key "count" that holds the count. If you want the count key to be something other than "count", pass the function a second argument.
You can use array_count_values in this case too. Example:
$values = array(
array('name' => 'Superman', 'time' => 60),
array('name' => 'Superman', 'time' => 60),
array('name' => 'Superman', 'time' => 50),
array('name' => 'Superman', 'time' => 40),
array('name' => 'Superman', 'time' => 50),
array('name' => 'Superman', 'time' => 60),
);
// map out into string then unique them
$uniques = array_map("unserialize", array_unique(array_map("serialize", $values)));
$count = array_count_values(array_map("serialize", $values)); // map out the arrays then get the counts
// then to merge the count
foreach($uniques as &$batch) {
foreach($count as $array => $v) {
if(unserialize($array) == $batch) { // if this particular key count is equal to this unique array, then push the count
$batch['count'] = $v;
}
}
}
echo '<pre>';
print_r($uniques);
Sample Output
Get Array and its values
make unique key on paypal_address
Use unique key to create temp array
Store all values with respective unique key in temp array
I am using time as unique key.
$tmpArr = Array();
$cnt = sizeof($arr);
for($i=0;$i<$cnt;$i++){
$time = $arr[$i]['time'];
if(!is_array($tmpArr[$time])){
$tmpArr[$time] = Array();
$tmpArr[$time]['count'] = 0;
}
$tmpArr[$time]['time'] = $arr[$i]['time'];
$tmpArr[$time]['name'] = $arr[$i]['name'];
$tmpArr[$time]['count'] = $tmpArr[$time]['count'] + 1;
}
print_r($tmpArr);
Note: Make changes in code according to your requirement

Cannot modify multidimensional array PHP

I have two arrays.
First one ($dcel) looks like this:
Array(
[1] => Array
(
[V1] => 5
[V2] => 2
[F1] => 4
[F2] => 1
[P1] => 7
[P2] => 4
)
etc..
Second one ($PctOldNew) looks like this:
Array(
[0] => Array
(
[old] => 1
[new] => 3
)
etc..
I'm trying to find the 'old' values (which are the initial) in the first array. Here's my code:
foreach ($dcel as $latura) {
for($i = 0; $i <= $nrPct; $i++){
if($PctOldNew[$i]['old'] == $latura[V1]){
$latura[V1] = $PctOldNew[$i]['new'];
}
}
}
If I output the $PctOldNew inside if statment, the output it's the correct answer, but if i try to modify $latura[V1] the $dcel remains untouched.
I've tried with reference, keys... but nothing works and i can't see what's wrong.
This works:
edit: adding a 2nd array element to $dcel to show how it works
<?php
$dcel = Array(
'1' => Array
(
'V1' => 1, // <-- note that i changed this value from your original '5' to '1' so that your condition will actually match something, since this example data set doesn't actually have something to match
'V2' => 2,
'F1' => 4,
'F2' => 1,
'P1' => 7,
'P2' => 4
)
'2' => Array
(
'V1' => 5,
'V2' => 2,
'F1' => 4,
'F2' => 1,
'P1' => 7,
'P2' => 4
)
);
$PctOldNew = Array(
'0' => Array
(
'old' => 1,
'new' => 3
)
);
foreach ($dcel as &$latura) { // <-- reference on &$latura
for($i = 0; $i <= $nrPct; $i++){
if($PctOldNew[$i]['old'] == $latura['V1']){
$latura['V1'] = $PctOldNew[$i]['new'];
}
}
}
echo "<pre>";print_r($dcel);
output
Array
(
[1] => Array
(
[V1] => 3
[V2] => 2
[F1] => 4
[F2] => 1
[P1] => 7
[P2] => 4
)
[2] => Array
(
[V1] => 5
[V2] => 2
[F1] => 4
[F2] => 1
[P1] => 7
[P2] => 4
)
)
#CrayonViolent it didn't work, i tried so many times.
I was playing right now with the code and it seems that like this it's working:
foreach ($dcel as $key => $value) {
foreach ($value as $val) {
for($i = 0; $i <= $nrPct; $i++){
if($PctOldNew[$i]['old'] == $value[V1])
$new = $PctOldNew[$i]['new'];
}
$val = $new;
}
$dcel[$key][V1] = $val;
}
...but i don't know why.
The most convenient way in your case would be using array_map() function
Like this:
$array = array(1,2,3,4,5);
$replacements = array(
array('old'=>1, 'new'=>11),
array('old'=>3, 'new'=>33),
);
$array = array_map(function($element){
global $replacements;
foreach($replacements as $r) if($r['old']==$element) return $r['new'];
return $element;
}, $array);
print_r($array);
Result:
Array ( 11, 2, 33, 4, 5 )
Another weird way is to use array_walk
array_walk(&$dcel, function($latura){
for($i = 0; $i <= $nrPct; $i++){
if($PctOldNew[$i]['old'] == $latura[V1]){
$latura[V1] = $PctOldNew[$i]['new'];
}
}
});
Or array_map
$dcel = array_map(function($latura){
for($i = 0; $i <= $nrPct; $i++){
if($PctOldNew[$i]['old'] == $latura[V1]){
$latura[V1] = $PctOldNew[$i]['new'];
}
}
return $latura;
}, $dcel);
(Not sure why array_walk and array_map have reversed parameter position)
Updated with the real reason and 2 more possible solutions
The reason you can't modify $latura is because you are using for...each loop which will pass $latura by-value rather than by-reference. Based on this reason, you have 2 more solutions,
Use for $dcel as $key => $latura then you can change $dcel[$key]
Use for $dcel as &$latura then you can change the item directly

Categories