Combine varied number of dynamically named arrays - php

I have seen the following: array_merge() How can I add a 'range' of an array name and the answers don't work for me.
I have an array that I am looping through in order to slice and convert certain currency strings to float numbers. I then have to array_merge them back together in order to work with the array and have been dynamically naming them so that I don't overwrite the previous array_merge. After doing so, I then need to combine all of the dynamically named arrays into one array.
Initially I had the following code, which worked great when I only had 3 nested arrays in the $order['product'] array. However, this number varies, and the code needs to do so as well.
$nr = 1;
foreach ($order['product'] as $product) {
$product_total = array_slice($product, 1);
array_walk($product_total, "convertCurrencyStringtoNumber");
${"final_product" . $nr} = array_merge($product, $product_total);
$nr++;
};
$arrays = array($final_product1, $final_product2, $final_product3);
var_dump($arrays);
This results in the following array:
array(3) {
[0]=> array(2) {
["source_code"]=> string(10) "408000-025"
["total"]=> float(18) }
[1]=> array(2) {
["source_code"]=> string(10) "408000-025"
["total"]=> float(17) }
[2]=> array(2) {
["source_code"]=> string(10) "408000-025"
["total"]=> float(2.75) } }
How do I implement a varied number of dynamically named arrays in the line:
$arrays = array($final_product1, $final_product2, $final_product3);
I attempted the following, but the array is nested incorrectly. Feel free to fix this code or come up with a better solution.
$nr = 1;
$i = 1;
foreach ($order['product'] as $product) {
$product_total = array_slice($product, 1);
array_walk($product_total, "convertCurrencyStringtoNumber");
${"final_product" . $nr} = array_merge($product, $product_total);
if ($nr > 0) {
$arrays = $final_product1;
for ($i = 2; $i <= $nr; $i++) {
$arrays = array_merge($arrays, ${"final_product" . $nr});
}
} else {
echo "There are no products in this order";
}
$nr++;
};
var_dump($arrays);
This results in the incorrectly nested array:
array(2) {
[0]=> array(2) {
[0]=> array(2) {
["source_code"]=> string(10) "408000-025"
["total"]=> float(18) }
[1]=> array(2) {
["source_code"]=> string(10) "408000-025"
["total"]=> float(17) } }
[1]=> array(2) {
["source_code"]=> string(10) "408000-025"
["total"]=> float(2.75) } }

Simply replace your dynamically single-named variables with an array:
$final_product = array();
foreach ($order['product'] as $product) {
$product_total = array_slice($product, 1);
array_walk($product_total, "convertCurrencyStringtoNumber");
$final_product[] = array_merge($product, $product_total);
};
var_dump($final_product);

Unless I'm missing something here... this should be as easy and simple as:
$final_array=[];
foreach ($order['product'] as $product) {
$final_array[]['total'] = (float) $product['whatever value 1 is...'];
$final_array[]['source_code'] = $product['source_code'];
}
var_dump($final_array);
If you need to apply convertCurrencyStringtoNumberbecause it does something weird to the variable then changethe seccond line to:
$final_array[]['total'] = convertCurrencyStringtoNumber(array_slice($product, 1));

Related

How to group a multidimensional array by multiple subarray values?

I checked this question and answers:
How to group a multidimensional array by a particular subarray value?
He wanted to group results by 'level'. But how would you do it to group it by 'level' first and then by 'type'?
Its pretty straight forward. Loop through $items array. Get each item's level and type and if they are not set yet, initialize them with an empty array. Then just push the "cust" value into the array.
I have given the code below.
I am assuming "$items" is an array which contains the input.
$g = [];
foreach($items as $k => $v) {
$l = $v["level"];
$t = $v["type"];
$c = $v["cust"];
if(!isset($g[$l])) {
$g[$l] = [];
}
if(!isset($g[$l][$t])) {
$g[$l][$t] = [];
}
$g[$l][$t][] = [
"cust" => $c
];
}
var_dump($g);
The output of this code would be like below:
array(3) {
[1]=>
array(1) {
["standard"]=>
array(2) {
[0]=>
array(1) {
["cust"]=>
string(6) "XT8900"
}
[1]=>
array(1) {
["cust"]=>
string(6) "XT8944"
}
}
}
[3]=>
array(1) {
["premier"]=>
array(2) {
[0]=>
array(1) {
["cust"]=>
string(6) "XT8922"
}
[1]=>
array(1) {
["cust"]=>
string(6) "XT8816"
}
}
}
[7]=>
array(1) {
["standard"]=>
array(1) {
[0]=>
array(1) {
["cust"]=>
string(6) "XT7434"
}
}
}
}
[P.S.]: You can also use sort to solve this problem easily. That's another way of solving this problem.

PHP: How to get unique content from array?

I have a array and I need unique contents. How can I get rid of duplicates in this $tmparray:
array(176) {
[0]=>
array(2) {
[0]=>
string(22) "/ads/67006/didi"
[1]=>
string(73) "/Content/Pictures/Scaled/7b5c69572fdb1569ced695c278072ae0.jpg"
}
[1]=>
array(2) {
[0]=>
string(22) "/ads/67006/didi"
[1]=>
string(73) "/Content/Pictures/Scaled/7b5c69572fdb1569ced695c278072ae0.jpg"
}
[2]=>
array(2) {
[0]=>
string(22) "/ads/67006/didi"
[1]=>
string(73) "/Content/Pictures/Scaled/7b5c69572fdb1569ced695c278072ae0.jpg"
}
[3]=>
array(2) {
[0]=>
string(19) "/ads/67010/sylvesta"
[1]=>
string(73) "/Content/Pictures/Scaled/83ebba04b8eabd0458cc6dbbb85581da.jpg"
}
[4]=>
array(2) {
[0]=>
string(19) "/ads/67010/sylvesta"
[1]=>
string(73) "/Content/Pictures/Scaled/83ebba04b8eabd0458cc6dbbb85581da.jpg"
}
[5]=>
array(2) {
[0]=>
string(19) "/ads/67010/sylvesta"
[1]=>
string(73) "/Content/Pictures/Scaled/83ebba04b8eabd0458cc6dbbb85581da.jpg"
}
But I want it to look like: (Only unique contents.)
array(176) {
[0]=>
array(2) {
[0]=>
string(22) "/ads/67006/didi"
[1]=>
string(73) "/Content/Pictures/Scaled/7b5c69572fdb1569ced695c278072ae0.jpg"
}
[1]=>
array(2) {
[0]=>
string(19) "/ads/67010/sylvesta"
[1]=>
string(73) "/Content/Pictures/Scaled/83ebba04b8eabd0458cc6dbbb85581da.jpg"
}
}
I have tried with:
array_unique($tmparray);
array_unique can't do what I want. Anyone have a idea how to solve this?
your question seems duplicate of this
How to remove duplicate values from a multi-dimensional array in PHP
i guess array_map will solve your problem
$input = array_map("unserialize", array_unique(array_map("serialize", $input)));
You can use this code:
$newarray= array();
foreach ($tmparray as $value) {
if (!in_array($value,$newarray)) {
$newarray[ ] = $value;
}
}
var_dump($newarray);
I assume that by duplicate you mean two items where either elements are matching, since you are mapping ads to their pictures, therefore:
$target = array();
$elementCount = count($tmparray);
$newElementCount = 0;
for ($i = 0; $i < $elementCount; $i++) {
$found = false;
for ($j = 0; (!$found) && (j < $newElementCount); j++) {
$found = $target[$j][0] === $tmparray[$i][0] || $target[$j][1] === $tmparray[$i][1];
}
if (!$found) {
$target[$newElementCount++]=$tmparray[$i];
}
}
PHP array_unique is used only for single dimensional arrays, for multidimensional you can do this by serializing multidimensional array, like below
<?php
$dataArray = [
0=>["/ads/67006/didi","/Content/Pictures/Scaled/7b5c69572fdb1569ced695c278072ae0.jpg"],
1=>["/ads/67010/sylvesta","/Content/Pictures/Scaled/83ebba04b8eabd0458cc6dbbb85581da.jpg"],
2=>["/ads/67006/didi","/Content/Pictures/Scaled/7b5c69572fdb1569ced695c278072ae0.jpg"],
3=>["/ads/67010/sylvesta","/Content/Pictures/Scaled/83ebba04b8eabd0458cc6dbbb85581da.jpg"],
];
$serilaized = [];
$newArr = [];
### serilaize each node of multi array and create a new single dimention array..
foreach($dataArray as $val){
$serilaized[] = serialize($val);
}
### now perform array unique..
$serilaized_unique = array_unique($serilaized);
## unserialize each node of uniqur array..
foreach($serilaized_unique as $val){
$newArr[] = unserialize($val);
}
echo "<pre>";print_r($newArr);
?>
This will give you:
Array
(
[0] => Array
(
[0] => /ads/67006/didi
[1] => /Content/Pictures/Scaled/7b5c69572fdb1569ced695c278072ae0.jpg
)
[1] => Array
(
[0] => /ads/67010/sylvesta
[1] => /Content/Pictures/Scaled/83ebba04b8eabd0458cc6dbbb85581da.jpg
)
)
In short you can perform this in single line code with array_map
$dataArray = array_map('unserialize', array_unique(array_map('serialize', $dataArray)));
I got it working with this line:
$tmparray = array_unique($tmparray, SORT_REGULAR);

PHP Arrays - Merge two arrays where a value is added together

I need some more help regarding PHP Arrays and the issue I am having. I have an array like this: -
array(2) {
[0]=>
array(2) {
[0]=>
array(2) {
["count"]=>
string(3) "100"
["id"]=>
int(46)
}
[1]=>
array(2) {
["count"]=>
string(3) "300"
["id"]=>
int(53)
}
}
[1]=>
array(1) {
[0]=>
array(2) {
["count"]=>
string(3) "200"
["id"]=>
int(46)
}
}
}
However, I would like it to look more like this as array: -
array(2) {
[0]=>
array(2) {
["count"]=>
string(3) "300" <--- This has been added from Array 1 and 2
["id"]=>
int(46)
}
[1]=>
array(2) {
["count"]=>
string(3) "300"
["id"]=>
int(53)
}
}
Basically if the same id is in both areas I want the count number to be added to each other but if it's not then it needs to just be left alone and included in the array.
I have used a number of array functions such as array_merge and array_push but I am running out of ideas of how this could work. I have also started working on a foreach with if statements but I just got myself completely confused. I just need a second pair of eyes to look at the issue and see howe it can be done.
Thanks again everyone.
Should work with something like this:
$idToCountArray = array(); //temporary array to store id => countSum
array_walk_recursive($inputArray, function($value,$key) { //walk each array in data structure
if(isset(value['id']) && isset($value['count'])) {
//we have found an entry with id and count:
if(!isset($idToCountArray[$value['id']])) {
//first count for id => create initial count
$idToCountArray[$value['id']] = intval($value['count']);
} else {
//n'th count for id => add count to sum
$idToCountArray[$value['id']] += intval($value['count']);
}
}
});
//build final structure:
$result = array();
foreach($idToCountArray as $id => $countSum) {
$result[] = array('id' => $id, 'count' => ''.$countSum);
}
Please note that I have not testet the code and there is probably a more elegant/performant solution.
You could use something like this:
$end_array = array();
function build_end_array($item, $key){
global $end_array;
if (is_array($item)){
if( isset($item["id"])){
if(isset($end_array[$item["id"]]))
$end_array[$item["id"]] = $end_array[$item["id"]] + $item["count"]*1;
else
$end_array[$item["id"]] = $item["count"]*1;
}
else {
array_walk($item, 'build_end_array');
}
}
}
array_walk($start_array, 'build_end_array');
Here is a fiddle.
Thank you ever so much everyone. I actually worked it by doing this: -
$fullArray = array_merge($live, $archive);
$array = array();
foreach($fullArray as $key=>$value) {
$id = $value['id'];
$array[$id][] = $value['count'];
}
$result = array();
foreach($array as $key=>$value) {
$result[] = array('id' => $key, 'count' => array_sum($value));
}
return $result;

How to make an average of array values

I have a database with multiple records. It is structured like this:
["data"]=>
array(5) {
[1]=>
[2]=>
array(11) {
[0]=>
string(1) "0"
[1]=>
string(8) "25000000"
[2]=>
string(3) "day"
[3]=>
string(5) "0.00%"
[4]=>
string(9) "404049904"
[5]=>
string(1) "0"
[6]=>
string(5) "0.00%"
[7]=>
string(1) "0"
[8]=>
string(1) "0"
[9]=>
string(1) "0"
[10]=>
string(3) "0.0"
}
I need to fetch the 8th record and I do this by using
public static function($data)
{
$array = [];
$path = $data->data[2];
foreach($path as $key => $item)
if($key > 1)
{
$array[] = [$item->data[8]];
}
return json_encode($array);
}
This foreach takes all the 8th values from the array but I need to display a single number which is the average of all the 8th values. How can I do this?
Once you've got your array containing all your data, simple sum the array and then divide by the size of the array.. something along these lines
$average = (array_sum($array) / count($array));
Of course you may want to check for count($array) being 0;
Because you put your value into a new array, you can not use array_sum to sum the values, so you should store it.
$sum = 0;
foreach($path as $key => $item)
if($key > 1) {
$array[] = [$item->data[8]];
$sum += $item->data[8];
}
}
$avg = ($sum / count($array); //the average
var_dump($avg);
If is it possible, just put it as a value:
$array[] = $item->data[8]; //no wrapping []
In this case, you can use $avg = array_sum($array) / count($array);
if (count($array)>0){
$avg = array_sum($array) / count($array);
}
I would personally do those calculations in the database before the data gets to your PHP script itself. See AVG().
If you can't for some reason use that I would output those values into a flat array and then just calculate the average. So something like :
function getAverage($data) {
$flatArray = array();
foreach ($data as $row) {
if (!empty($row->8)) {
$flatArray[] = $row->8;
}
}
return (array_sum($flatArray)/count($flatArray));
}
EDIT: Moved to Object traversing on the data row, sorry, missed that initially and thought it was an array in all the nests.
Since you have a loop within your static Method; why not do the calculation therein and return it or add it to the JSON Data if You need your Data in JSON Format? Here's what's implied by the above:
public static function getAverageSum($data) {
$array = [];
$path = $data->data[2];
$sumTotal = 0.00; //<== YOU COULD JUST SUM IT DIRECTLY WITHOUT USING AN ARRAY
foreach($path as $key => $item) {
if ($key > 1) {
$array[] = $item->data[8];
$sumTotal += floatval($item->data[8]);
}
}
// IF YOU ARE ONLY INTERESTED IN THE AVERAGE SUM YOU COULD EVEN ADD IT IT TO THE $array AS AN EXTRA KEY
// LIKE SO:
$arrLen = count($array);
$array['avgSum'] = $sumTotal/$arrLen;
// IF YOU NEED YOUR DATA IN JSON... THEN RETURN THE JSON ENCODED DATA WITH SUM AS PART OF THE DATA.
// YOU'D HAVE NO NEED FOR array_sum() SINCE YOU DID YOUR PREP-WORK ALREADY...
return json_encode($array);
// ALTERNATIVELY; IF ALL YOU NEED IS JUST THE AVERAGE SUM; YOU COULD AS WELL DIRECTLY RETURN $sumTotal/$arrLen
return ($sumTotal/$arrLen);
}

find / select specified ID in array php

i have array with database, and have to select only this items what have "tid" = 1
array(3) {
[1]=>
array(4) {
["tid"]=> "1"
["title"]=> "Google"
["url"]=> "http://google.com/"
["description"]=> "A very efficient search engine."
}
[2]=>
array(4) {
["tid"]=> "2"
["title"]=> "Facebook"
["url"]=> "http://facebook.com/"
["description"]=> "Trade securities, currently supports nearly 1000 stocks and ETFs"
}
[3]=>
array(4) {
["tid"]=> "1"
["title"]=> "Yandex"
["url"]=> "http://yandex.ru/"
["description"]=> "Another efficient search engine popular in Russia"
}
}
how can i select only this items from array what have "tid" = 1?
<?php
$final_arr = array();
foreach($tid_arrs as $tid_arr){
if($tid_arr['tid'] == 1){
$final_arr[] = $tid_arr;
}
}
print_r($final_arr);
?>
$filteredArray = array();
for($i = 0, $end = count($array);$i < $end;i++)
{
if($array[$i]["tid"] === "1")
{
$filderedArray[] = $array[$i];
}
}
That way $filteredArray will contain solely the items with tid 1;
Try array_filter function: http://php.net/manual/en/function.array-filter.php this should help.
print_r(array_filter($array, "filter_function"));
function filter_function($element){
return (int)$element['tid'] === 1;
}
let's say you starting array is $arr.
$result = array();
foreach ($arr as $arrItem) {
if ((array_key_exists('tid', $arrItem)) && ($arrItem['tid'] == "1")){
$result[] = $arrItem;
}
}
$result should be what you are excepted.

Categories