I am having trouble thinking of the logic with the following problem:
I have the following array (has been snipped, as its much larger)
Array
(
[0] => Array
(
[code] => LAD001
[whqc] => GEN
[stocktag] => NONE
[qty] => 54
)
[1] => Array
(
[code] => LAD001
[whqc] => GEN
[stocktag] => NONE
[qty] => 6
)
[2] => Array
(
[code] => LAD004
[whqc] => HOLD
[stocktag] => NONE
[qty] => 6
)
)
I basically need to comebine all the keys in this array so that where the code, whqc and stocktag are the same, add the qty values together. With the example below, I need to end up with this:
Array
(
[0] => Array
(
[code] => LAD001
[whqc] => GEN
[stocktag] => NONE
[qty] => 60
)
[1] => Array
(
[code] => LAD004
[whqc] => HOLD
[stocktag] => NONE
[qty] => 6
)
)
As the first and second keys of the array had the same code, whqc and stocktag, the qty's have been added together into the one key.
Any ideas?
I would suggest combining the group values in to a hash, storing the full array under the hash as a key and if you have a duplicate, add the quantity, then do array_values() to pull the results.
$aggregated = array();
foreach ($records as $cRec) {
// The separator | has been used, if that appears in the tags, change it
$cKey = md5($cRec['code'] . '|' . $cRec['whqc'] . '|' . $cRec['stocktag']);
if (array_key_exists($cKey, $aggregated)) {
$aggregated[$cKey]['qty'] += $cRec['qty'];
} else {
$aggregated[$cKey] = $cRec;
}
}
// Reset the keys to numerics
$aggregated = array_values($aggregated);
I would try something like:
$output = array();
foreach($array as $details){
//make distinct key
$key = $details['code'].'_'.$details['whqc'];
if(!isset($output[$key])){
$output[$key] = $details;
}else{
$output[$key]['qty'] += $details['qty'];
$output[$key]['stocktag'] = $details['stocktag'];
}
}
$output = array_values($output);
print_r($output);
update: Orbling was first ;-)
Related
I have JSON API response which look something like this
Array
(
[sections] => Array
(
[0] => Array
(
[id] => 115000089967
[url] => xxxxx
[html_url] => ArticleHTML1
[category_id] => 204458828
[position] => 0
[sorting] => manual
[created_at] => 2016-12-19T14:56:23Z
[updated_at] => 2017-02-03T08:23:04Z
[name] => ArticleName1
[description] =>
[outdated] =>
)
[1] => Array
(
[id] => 207077828
[url] => xxxxxx
[html_url] => ArticleHTML2
[category_id] => 204458828
[position] => 1
[sorting] => manual
[created_at] => 2016-11-14T09:28:30Z
[updated_at] => 2017-02-02T09:15:42Z
[name] => ArticleName2
[description] =>
[outdated] =>
)
)
[page] => 1
[per_page] => 30
[page_count] => 1
[sort_by] => position
[sort_order] => asc
)
I have successfully iterated this with foreach, so return looks like this:
ArticleName1 ArticleHTML1
ArticleName2 ArticleHTML2
So I took [name] and [html_url] from each like this:
$details1 = array('name');
$details2 = array('html_url');
foreach($sections['sections'] as $article) {
foreach($details1 as $detail) {
echo "$article[$detail] ";
}
foreach($details2 as $detail) {
echo "$article[$detail]\n";
}
}
But what I want next is that, that response should be exploded to one single array like this:
Array
(
[0] => ArticleName1 ArticleHTML1
[1] => ArticleName2 ArticleHTML2
)
I already managed to explode those to individual arrays:
foreach($sections['sections'] as $article) {
foreach($details1 as $detail) {
$name = "$article[$detail] ";
}
foreach($details2 as $detail) {
$url = "$article[$detail]\n";
}
$string = $name . $url;
$array = explode(' ', $string, 1);
print_r($array);
}
but I need just one array.
How? I'm lost or just doesn't understand, am I even close?
EDIT
The thing here is that the JSON dump is pretty large and I only need few things (name and url). So I was thinking that I first grab the whole thing, then I just take the names and urls (like the first foreach is doing), and then put those back to array. Because from those names and urls I need only last 12 keys, and taking those from sinlge array would be easy.
Tho it would be perfect, if I could sort out the keys which I don't want, in the first place. That would solve my problem. Then I wouldn't need a new array etc.
You're making this much more difficult than it needs to be. It's just a single loop:
$array = array();
foreach ($sections['sections'] as $article) {
$array[] = $article['name'] . ' ' . $article['html_url'];
}
I want to merge two arrays in order to get the data as per my requirement.
I am posting my result, please have a look.
First array:
Array
(
[0] => Array
(
[km_range] => 300
[id] => 2
[car_id] => 14782
)
[1] => Array
(
[km_range] => 100
[id] => 3
[car_id] => 14781
)
[2] => Array
(
[km_range] => 300
[id] => 4
[car_id] => 14783
)
)
Second array:
Array
(
[0] => Array
(
[user_id] => 9c2e00508cb28eeb1023ef774b122e86
[car_id] => 14783
[status] => favourite
)
)
I want to merge the second array into the first one, where the value at key car_id matches the equivalent value; otherwise it will return that field as null.
Required output:
<pre>Array
(
[0] => Array
(
[km_range] => 300
[id] => 2
[car_id] => 14782
)
[1] => Array
(
[km_range] => 100
[id] => 3
[car_id] => 14781
)
[2] => Array
(
[km_range] => 300
[id] => 4
[car_id] => 14783
[fav_status] => favourite
)
)
Since the merge is so specific I would try something like this:
foreach ($array1 as $index => $a1):
foreach ($array2 as $a2):
if ($a1['car_id'] == $a2['car_id']):
if ($a2['status'] == "favourite"):
$array1[$index]['fav_status'] = "favourite";
endif;
endif;
endforeach;
endforeach;
You might be able to optimize the code more but this should be very easy to follow...
Another way to achieve this without using the index syntax is to reference the array elements in the foreach by-reference by prepending the ampersand operator:
foreach($firstArray as &$nestedArray1) {
foreach($secondArray as $nestedArray2) {
if ($nestedArray1['car_id'] == $nestedArray2['car_id']) {
$nestedArray1['fav_status'] = $nestedArray2['status'];
}
}
}
You can see it in action in this Playground example.
Technically you asked about merging the arrays. While the keys would be different between the input arrays and the desired output (i.e. "status" vs "fav_status"), array_merge() can be used to merge the arrays.
if ($nestedArray1['car_id'] == $nestedArray2['car_id']) {
$nestedArray1 = array_merge($nestedArray1, $nestedArray2);
}
Playground example.
Additionally the union operators (i.e. +, +=) can be used.
If you want to append array elements from the second array to the first array while not overwriting the elements from the first array and not re-indexing, use the + array union operator1
if ($nestedArray1['car_id'] == $nestedArray2['car_id']) {
$nestedArray1 += nestedArray1;
}
Playground example.
1http://php.net/manual/en/function.array-merge.php#example-5587
here is my code
array 1:
Array
(
[0] => Array
(
[id] => 42166
[Company_Website] => http://www.amphenol-highspeed.com/
[company_name] => Amphenol High Speed Interconnect
[city_name] => New York
[country_name] => USA
[comp_img] =>
)
)
array 2:
Array
(
[0] => Array
(
[Product_Name] => CX to CX,Amphenol High Speed Active,Serial Attached SCSI
[company_id] => 42166
)
)
php code:
$total = count($result);
$i=0;
foreach ($result as $key=>$value) {
$i++;
$company_id= implode(",",(array)$value['id']);
if ($i != $total)
echo',';
}
code to fetch array 2:
foreach ($res as $key1=>$value1) {
echo $total;
$event[$value['company_name']] = $value1['Product_Name'];
if($value1['company_id']==$company_id )
{
echo " match";
//$key[['company_name']]= $value1['Product_Name'];
}
else
{
echo "not matched";
}
}
what i need create a new index if company_id is match with id of another array.
that is product_name.
if product name is there just create index otherwise show null.
i want show in key=> value .
output should be like:
Array
(
[0] => Array
(
[id] => 42166
[Company_Website] => http://www.amphenol-highspeed.com/
[company_name] => Amphenol High Speed Interconnect
[city_name] => New York
[country_name] => USA
[comp_img] =>
[Product_Name] => CX to CX,Amphenol High Speed Active,Serial Attached SCSI
)
)
Your all problems with keys in arrays will disappear when you will start using company ids as a keys.
To reindex you arrays, you can use:
$array1 = array_combine(array_column($array1, 'id'), $array1);
$array2 = array_combine(array_column($array2, 'company_id'), $array2);
In the output you will get:
array 1:
Array
(
[42166] => Array
(
[id] => 42166
...
)
)
And array 2 will looks similiar - id as a key.
So accessing to the elements using ids as a keys is a piece of cake right now.
So I am print_r-ing an array, generated as follows:
while ($twitgroup = mysql_fetch_array($resulttwitter)) {
print_r($twitgroup);
}
I get this output (with multiple more arrays, dependent on rows).
Array ( [0] => composed [category] => composed [1] => 330 [value] => 330 [2] => 1344384476.94 [timestamp] => 1344384476.94 ) Array ( [0] => elated [category] => elated [1] => 2034 [value] => 2034 [2] => 1344384476.94 [timestamp] => 1344384476.94 ) Array ( [0] => unsure [category] => unsure [1] => 2868 [value] => 2868 [2] => 1344384476.94 [timestamp] => 1344384476.94 ) Array ( [0] => clearheaded [category] => clearheaded [1] => 1008 [value] => 1008 [2] => 1344384476.94 [timestamp] => 1344384476.94 ) Array ( [0] => tired [category] => tired [1] => 2022 [value] => 2022 [2] => 1344384476.94 [timestamp] => 1344384476.94 )
I want to be able to pull individual values here, but I'm having trouble. I'm trying to use a while loop on these arrays, but I think maybe that's wrong. Should I perhaps use a foreach loop, and then on the output of that foreach, access each element of the array?
Say for example, I want to grab composed, and the value of composed. How would I do that?
I'm pretty good with arrays/lists in Python, but my experience with arrays in PHP is somewhat lacking.
Use
while ($row = mysql_fetch_assoc($resulttwitter)) {
$twitgroup[$row['category']] = $row;
}
echo $twitgroup['composed']['value']; // outputs 330
echo $twitgroup['composed']['timestamp']; // outputs 1344384476.94
If you only want categories and their values use
while ($row = mysql_fetch_assoc($resulttwitter)) {
$twitgroup[$row['category']] = $row['value'];
}
echo $twitgroup['composed']; // outputs 330
Replace mysql_fetch_array with mysql_fetch_assoc to eliminate duplicates. Then this:
while ($twitgroup = mysql_fetch_assoc($resulttwitter))
{
foreach ($twitgroup as $key => $value)
{
echo "$key => $value\n";
}
}
You could also get the elements by name:
while ($twitgroup = mysql_fetch_assoc($resulttwitter))
{
echo "category => " . $twitgroup["category"] . "\n";
echo "value => " . $twitgroup["value"] . "\n";
echo "timestamp => " . $twitgroup["timestamp"] . "\n";
}
mysql_fetch_array includes each field twice in the result, one associated with a numeric key and one with the field name.
That is why you have
[0] => composed
[category] => composed
[1] => 330
[value] => 330
You can access field either like :
$twitgroup[0]
or like :
$twitgroup['category']
So, you can access your each row like :
while ($twitgroup = mysql_fetch_array($resulttwitter)) {
print $twitgroup['category']; // or print $twitgroup['0'];
print $twitgroup['value']; // // or print $twitgroup['1'];
// or by the corresponding numeric indices.
}
If at all you want to limit your result to either numeric or Associative array, add an additional flag (result_type) to your mysql_fetch_array :
mysql_fetch_array ($resulttwitter, MYSQL_ASSOC) // or mysql_fetch_array ($resulttwitter, MYSQL_NUM)
Having said all this, it is highly discouraged using mysql_* functions in PHP since they are deprecated. You should use either mysqli or PDO instead.
This is what you have:
Array (
[0] => composed
[category] => composed
[1] => 330
[value] => 330
[2] => 1344384476.94
[timestamp] => 1344384476.94
) Array (
[] =>
[] =>
...
) ...
Arrays in PHP are called associative arrays because they can have
either keys out of integers, strings or anything else.
You have an array with arrays in it.
To access the individual fields, it would be most convenient to use a
for each loop.
$record=0;
foreach ($array as $k => $subArray) {
$record++;
foreach($subArray as $field => $value) {
printf("%d: %s = %s\n", $record, $field, $value);
}
}
Its seems to me that there is something wrong with the way you are fetching
the data, becasue half the fields seem redundant. You can use the string keys
to figure out the contents. so there is no need for the n => name entries.
If that can't be helped, I guess you could iterate over the values with
$ix=0;
for ($i=0; $i < (count($array)/2); $i++){
printf("%s\n", $array[$ix]);
$ix++;
}
I am building an MLM software in PHP, one of its function is to count the downline performance.
It creates an array from parent-child relationships, which can be seen below.
How can I get the performance (array key: points) of my children, and their grandchildren as well through the fifth down level?
Array
(
[children] => Array
(
[0] => Array
(
[id] => 1
[name] => Medvedev
[email] =>
[points] => 7
[children] => Array
(
[0] => Array
(
[id] => 3
[name] => Putin
[email] =>
[points] => 4
[children] => Array
(
[0] => Array
(
[id] => 5
[name] => Nathan
[email] =>
[points] => 3
)
[1] => Array
(
[id] => 7
[name] => George
[email] =>
[points] => 666
)
)
)
[1] => Array
(
[id] => 4
[name] => Lucas
[email] =>
[points] => 43
)
)
)
)
[id] => 27
[name] => Boss
[email] =>
[points] => 99999
)
this should work with unlimited depth starting from a main array like
$array = array(
'children' => array( /* ADD HERE INFINITE COMBINATION OF CHILDREN ARRAY */ ),
'id' => #,
'name' => '',
'email' => '',
'points' => #
);
function recursive_children_points($arr) {
global $hold_points;
if (isset($arr['points'])) {
$hold_points[] = $arr['points'];
}
if (isset($arr['children'])) {
foreach ($arr['children'] as $children => $child) {
recursive_children_points($child);
}
}
return $hold_points;
}
$points = recursive_children_points($array);
print "<pre>";
print_r($points);
/**
// OUTPUT
Array
(
[0] => 99999
[1] => 7
[2] => 4
[3] => 3
[4] => 666
[5] => 43
)
**/
print "<pre>";
In my opinion this calls for recursion because you'll do the same thing over each flat level of the array: add the points.
so you'll need to
loop over each array
add points found
if we find any children, do it again but with children array
while keeping track of levels and jumping out if you reach your limit
With that in mind I thought of the following solution:
<?php
$values = array();
//first
$values[] = array('name'=>'andrej','points'=>1,'children'=>array());
$values[] = array('name'=>'peter','points'=>2,'children'=>array());
$values[] = array('name'=>'mark','points'=>3,'children'=>array());
//second
$values[0]['children'][] = array('name'=>'Sarah','points'=>4,'children'=>array());
$values[2]['children'][] = array('name'=>'Mike','points'=>5,'children'=>array());
//third
$values[0]['children'][0]['children'][] = array('name'=>'Ron','points'=>6,'children'=>array());
//fourth
$values[0]['children'][0]['children'][0]['children'][] = array('name'=>'Ronny','points'=>7,'children'=>array());
//fifth
$values[0]['children'][0]['children'][0]['children'][0]['children'][] = array('name'=>'Marina','points'=>10,'children'=>array());
//sixth
$values[0]['children'][0]['children'][0]['children'][0]['children'][0]['children'][] = array('name'=>'Pjotr','points'=>400,'children'=>array());
function collect_elements($base, $maxLevel,$child='children',$gather='points', &$catch = array(), $level = 0) {
/* I pass $catch by reference so that all recursive calls add to the same array
obviously you could use it straight away but I return the created array as well
because I find it to be cleaner in PHP (by reference is rare and can lead to confusion)
$base = array it works on
$maxLevel = how deep the recursion goes
$child = key of the element where you hold your possible childnodes
$gather = key of the element that has to be collected
*/
$level++;
if($level > $maxLevel) return; // we're too deep, bail out
foreach ($base as $key => $elem) {
// collect the element if available
if(isset($elem[$gather])) $catch[] = $elem[$gather];
/*
does this element's container have children?
[$child] needs to be set, [$child] needs to be an array, [$child] needs to have elements itself
*/
if (isset($elem[$child]) && is_array($elem[$child]) && count($elem[$child])){
// if we can find another array 1 level down, recurse that as well
collect_elements($elem[$child],$maxLevel,$child,$gather, $catch,$level);
}
}
return $catch;
}
print array_sum(collect_elements($values,5)) . PHP_EOL;
collect_elements will collect the element you're interested in (until maximum depth is reached) and append it to a flat array, so that you can act on it upon return. In this case we do an array_sum to get the total of poins collected
Only the first for parameters are interesting:
collect_elements($base, $maxLevel,$child='children',$gather='points'
not optional:
$base is the array to work on
$maxLevel is the maximum depth the function needs to descend into the arrays
optional:
$child defines the key of the element that contains the children of current element (array)
$gather defines the key of the element that contains what we want to gather
The remaining parameters are just ones used for recursion