Grouping items in assoc. array - php

I have an associative array with the following contents:
Array
(
[L_TIMESTAMP0] => 2011%2d10%2d16T16%3a57%3a38Z
[L_TIMESTAMP1] => 2011%2d10%2d16T16%3a45%3a23Z
[L_TIMESTAMP2] => 2011%2d10%2d16T16%3a35%3a54Z
[L_TIMEZONE0] => GMT
[L_TIMEZONE1] => GMT
[L_TIMEZONE2] => GMT
[L_STATUS0] => Completed
[L_STATUS1] => Completed
[L_STATUS2] => Completed
[TIMESTAMP] => 2011%2d10%2d16T17%3a58%3a39Z
)
What I want to do is to 'group' all instances of L_TIMESTAMP0, L_TIMEZONE0 and L_STATUS0 (and L_TIMESTAMP1, L_TIMEZONE1, L_STATUS1) into their own array, or as part of a multidimensional array. But I simply can't seem to figure out how I would go about accomplishing this.
The expected results would be:
Array
(
[L_TIMESTAMP0] => 2011%2d10%2d16T16%3a57%3a38Z
[L_TIMEZONE0] => GMT
[L_STATUS0] => Completed
)
Array
(
[L_TIMESTAMP1] => 2011%2d10%2d16T16%3a45%3a23Z
[L_TIMEZONE1] => GMT
[L_STATUS1] => Completed
)
I figured this would be simple with a simple for-loop, but that doesn't give me the results I'm looking for.
Any ideas?
It's likely something very obvious, but I've spent the last few days with this and I can't figure it out (although that probably says more about my skills than the problem)
edit:
To add; I don't need the exact code for my particular question, but any pointers as to what direction I should look into would be greatly appreciated.

<?php
$groupRegex = '/([0-9]+)$/';
$multiArray = array();
$assocArray = array (
"L_TIMESTAMP0" => "2011%2d10%2d16T16%3a57%3a38Z",
"L_TIMESTAMP1" => "2011%2d10%2d16T16%3a45%3a23Z",
"L_TIMESTAMP2" => "2011%2d10%2d16T16%3a35%3a54Z",
"L_TIMEZONE0" => "GMT",
"L_TIMEZONE1" => "GMT",
"L_TIMEZONE2" => "GMT",
"L_STATUS0" => "Completed",
"L_STATUS1" => "Completed",
"L_STATUS2" => "Completed",
"TIMESTAMP" => "2011%2d10%2d16T17%3a58%3a39Z"
);
foreach( $assocArray as $key => $value ) {
preg_match( $groupRegex, $key, $group );
if( !isset($group[1]) ){
continue;
}
$group = intval( $group[1] );
if( is_array( $multiArray[$group] ) ) {
$multiArray[$group][$key] = $value;
}
else {
$multiArray[$group] = array( $key => $value );
}
}
echo "<pre>";
print_r( $multiArray);
echo "</pre>";
?>
result
Array
(
[0] => Array
(
[L_TIMESTAMP0] => 2011%2d10%2d16T16%3a57%3a38Z
[L_TIMEZONE0] => GMT
[L_STATUS0] => Completed
)
[1] => Array
(
[L_TIMESTAMP1] => 2011%2d10%2d16T16%3a45%3a23Z
[L_TIMEZONE1] => GMT
[L_STATUS1] => Completed
)
[2] => Array
(
[L_TIMESTAMP2] => 2011%2d10%2d16T16%3a35%3a54Z
[L_TIMEZONE2] => GMT
[L_STATUS2] => Completed
)
)

$restructuring = true;
$count = 0;
$new_array = array();
while($restructuring)
{
$restructuring = false;
foreach($original_array as $oa)
{
if(!array_key_exists($count, $new_array) && array_key_exists('L_TIMESTAMP'.$count, $original_array))
{
$new_element = array();
foreach(array('TIMESTAMP', 'TIMEZONE', 'STATUS') as $e)
if(!empty($original_array['L_'.$e.$count])) $new_element[$e.$count] = $original_array['L_'.$e.$count];
$new_array[] = $new_element;
$count++;
$restructuring = true;
}
}
}
Given $original_array as defined in the question, the $new_array will be:
Array
(
[0] => Array
(
[TIMESTAMP0] => 2011%2d10%2d16T16%3a57%3a38Z
[TIMEZONE0] => GMT
[STATUS0] => Completed
)
[1] => Array
(
[TIMESTAMP1] => 2011%2d10%2d16T16%3a45%3a23Z
[TIMEZONE1] => GMT
[STATUS1] => Completed
)
[2] => Array
(
[TIMESTAMP2] => 2011%2d10%2d16T16%3a35%3a54Z
[TIMEZONE2] => GMT
[STATUS2] => Completed
)
)

Related

Array Combine with same year

I hope you guys fine, From last 3-4 hours I try to combine year in the same array set and unset all other arrays which are duplicate (I unable to explain correctly, please check the array example below)., but so far no luck, I tried and I know this isn't the correct way, if anybody has a solution for this please share.
Can somebody tell me how to combine same year in an array and unset other arrays at the same time, I tried but failed, no luck.
Try to do that way, but faild misrably:
foreach ($class as $i=>$class_list){
echo $i;
foreach ($class_list as $key=>$value){
$e=0;
foreach ($class_list as $value2){
if ($value['name']==$value2['name']){
echo 'match';
$class['packages'][$key]['year'][$e]=$value['year'];
}
$e++;
}
}
}
Actual Array:
Array
(
[packages] => Array
(
[0] => Array
(
[name] => atif.ali
[year] => 2019
)
[1] => Array
(
[name] => atif.ali
[year] => 2018
)
[2] => Array
(
[name] => atif.ali
[year] => 2017
)
[3] => Array
(
[name] => khatija.abbas
[year] => 2017
)
)
)
Need output like this:
Array
(
[packages] => Array
(
[0] => Array
(
[name] => atif.ali
[year] => Array
(
[0] 2019
[1] 2018
[2] 2017
)
)
[1] => Array
(
[name] => khatija.abbas
[year] => 2017
)
)
)
P.S: array can be different but "year" and "name" structure always same.
It's probably easiest to just create a new array in the format you require. You can do that by looping over the values inside packages, checking for the existence of the name in the new array, and if it exists, adding the current year to that value. If it doesn't exist, just create a new entry for that name.
$new_array = array('packages' => array());
foreach ($array['packages'] as $value) {
if (($k = array_search($value['name'], array_column($new_array['packages'], 'name'))) !== false) {
$new_array['packages'][$k]['year'][] = $value['year'];
}
else {
$new_array['packages'][] = array('name' => $value['name'], 'year' => array($value['year']));
}
}
print_r($new_array);
Output:
Array
(
[packages] => Array
(
[0] => Array
(
[name] => atif.ali
[year] => Array
(
[0] 2019
[1] 2018
[2] 2017
)
)
[1] => Array
(
[name] => khatija.abbas
[year] => Array (
[0] => 2017
)
)
)
)
Demo on 3v4l.org
Update
If you really want the year field not to be an array when there is only one value, this code will do that for you; it only makes it into an array when a second or subsequent value is seen.
$new_array = array('packages' => array());
foreach ($array['packages'] as $value) {
if (($k = array_search($value['name'], array_column($new_array['packages'], 'name'))) !== false) {
if (is_array($new_array['packages'][$k]['year'])) {
$new_array['packages'][$k]['year'][] = $value['year'];
}
else {
$new_array['packages'][$k]['year'] = array($new_array['packages'][$k]['year'], $value['year']);
}
}
else {
$new_array['packages'][] = $value;
}
}
print_r($new_array);
Demo on 3v4l.org
Try this
$class = ['packages' => [['name' => 'atif.ali', 'year' => 2019], ['name' => 'atif.ali', 'year' => 2018], ['name' => 'atif.ali', 'year' => 2017], ['name' => 'khatija.abbas', 'year' => 2017]]];
$new_class = [];
foreach ($class['packages'] as $key => $class_list) {
if( ! isset($new_class[$class_list['name']])){
$new_class[$class_list['name']] = $class_list;
}else{
if(is_array($new_class[$class_list['name']]['year'])){
$new_class[$class_list['name']]['year'][] = $class_list['year'];
}else{
$prev_year = $new_class[$class_list['name']]['year'];
$new_class[$class_list['name']]['year'] = [$prev_year, $class_list['year']];
}
}
}
$class['packages'] = $new_class;
I see there are some other responses while I wrote my own. First of all here you have the piece of code:
<?php
// Input data
$input = array('packages' => array(
array('name' => 'atif.ali', 'year' => 2019),
array('name' => 'atif.ali', 'year' => 2018),
array('name' => 'atif.ali', 'year' => 2017),
array('name' => 'khatija.abbas', 'year' => 2017),
));
$output = array(); // Create new array to store the final result
foreach ($input['packages'] as $package) { // we are only interested in 'packages', let's iterate over them
$name = $package['name'];
$year = $package['year'];
if (!isset($output[$name])) { // First time we see this name?
$output[$name] = array('name' => $name, 'year' => []); // Let's create an "empty" structure.
}
if (!in_array($year, $output[$name]['year'])) { // First time we see this year for this name?
$output[$name]['year'][] = $year; // Let's add it
}
}
// Reformatting to fit your needs (nest everything under 'packages' and remove the names from resulting dictionary keys)
$output = array('packages' => array_values($output));
var_dump($output);
Let me note the key issues/concepts:
As others suggested: create a new structure for your output. Reusing the same array will probably cause you nightmares. What if you want to later use the original input? Check inmutability and stateless programming.
It is easier if you use a map/dictionary/associative-array for grouping instead of an array itself. It is easier (and faster) to check if a key exists in a map than if an element exists in an array.
All this is using basic php/programming stuff. It can also be achieved by using array_reduce. If you are curious take a look at it :)
Give the code and comments a look and if you have any doubt let me know.
Another option is to create a new result where the key packages already exists. Then use the name as the key so you can check if the key already exists.
If it does not, add a new entry. If it does already exists, index into the new $result converting what is already there to an array so that the first entry which is a string becomes an array.
$arrays = [
"packages" => [
["name" => "atif.ali", "year" => "2019"],
["name" => "atif.ali", "year" => "2018"],
["name" => "atif.ali", "year" => "2017"],
["name" => "khatija.abbas", "year" => "2019"]
]
];
$result = ["packages" => []];
foreach ($arrays["packages"] as $array) {
if(!array_key_exists($array['name'], $result["packages"])) {
$result["packages"][$array['name']] = $array;
continue;
}
$result["packages"][$array['name']]['year'] = (array)$result["packages"][$array['name']]['year'];
$result["packages"][$array['name']]['year'][] = $array['year'];
}
print_r($result);
See a php demo
If you want numerical indexes instead, you could use array_values like this example
I've written this sort of quickly -- I'll look at it again in the morning when I've hopefully had a chance to rest and rethink how to do this with one loop. This seems to work for me. NOTE I did not include the 'packages' key, but the code can be modified by adding it in front of that particular section.
Edit
Had a quick second to think about what I did, perhaps this is what you're looking for:
<?php
$raw = [
[
'name'=>'atif.ali',
'year'=>2018
],
[
'name'=>'atif.ali',
'year'=>2019
],
[
'name'=>'atif.ali',
'year'=>2017
],
[
'name'=>'kahitja.abal',
'year'=>2019
],
[
'name'=>'kahitja.abal',
'year'=>2018
],
[
'name'=>'john.smith',
'year'=>2017
],
[
'name'=>'john.smith',
'year'=>2018
],
];
$map_index = [];
$final = [];
for($i = 0; $i< count($raw); $i++) {
if(!isset($map_index[$raw[$i]['name']])){
$map_index[$raw[$i]['name']] = count($final);
$final[count($final)] = ['name'=>$raw[$i]['name'], 'years'=>[]];
}
$index = $map_index[$raw[$i]['name']];
$final[$index]['years'][]=$raw[$i]['year'];
}
echo '<pre>';
print_r($final);
?>
Here is an example, just build a new array and swap.
<?php
$data =
[
[
'name' => 'Bilbo Baggins',
'year' => 2010
],
[
'name' => 'Bilbo Baggins',
'year' => 2011
],
[
'name' => 'Frodo Baggins',
'year' => 1999
]
];
foreach($data as $item) {
$output[$item['name']]['name'] = $item['name'];
$output[$item['name']]['year'][] = $item['year'];
}
print_r($output);
Output:
Array
(
[Bilbo Baggins] => Array
(
[name] => Bilbo Baggins
[year] => Array
(
[0] => 2010
[1] => 2011
)
)
[Frodo Baggins] => Array
(
[name] => Frodo Baggins
[year] => Array
(
[0] => 1999
)
)
)
If you don't like the new keys, call array_values on the result.

how to combine 2 array values into single one by common value

1.fetching the values from a same table with different date
<?php
$date= date("Y-m-d");;
$prev_date = date('Y-m-d', strtotime($date .' -1 day'));
$result_yest=mysql_query("SELECT isp,sum(sent) AS `sent_yest` FROM red_global WHERE status_date='$prev_date' and sent > 0 group by 1",$link1);
$data_yest = array(); // create a variable to hold the information
while (($row_yest = mysql_fetch_array($result_yest, MYSQL_ASSOC)) !== false){
$data_yest[] = $row_yest; // add the row in to the results (data) array
}
print_r($data_yest);
$result_today=mysql_query("SELECT isp,sum(sent) AS `sent_today` FROM red_global WHERE status_date='$date' and sent > 0 group by 1",$link1);
$data_today = array(); // create a variable to hold the information
while (($row_today = mysql_fetch_array($result_today, MYSQL_ASSOC)) !== false){
$data_today[] = $row_today; // add the row in to the results (data) array
}
print_r($data_today);
exit;
?>
2.Array results in which one array contains yesterday's sent count and another one aray contains today's sent count both array having the common isp
Array (
[0] => Array ( [isp] => aol [sent_yest] => 46838 )
[1] => Array ( [isp] => gmail [sent_yest] => 33015 )
[2] => Array ( [isp] => juno [sent_yest] => 93544 )
[3] => Array ( [isp] => roadrunner [sent_yest] => 6181 )
[4] => Array ( [isp] => yahoo [sent_yest] => 71444 )
)
Array (
[0] => Array ( [isp] => aol [sent_today] => 14135 )
[1] => Array ( [isp] => att [sent_today] => 624 )
[2] => Array ( [isp] => gmail [sent_today] => 21263 )
[3] => Array ( [isp] => juno [sent_today] => 74934 )
[4] => Array ( [isp] => roadrunner [sent_today] => 939 )
[5] => Array ( [isp] => yahoo [sent_today] => 22059 )
)
Now i need a result like this isp name, yesterday's sent count, today's sent count
[isp, sent_yest, sent_today],
[aol, 46838, 14135],
[att, 0, 624],
[gmail, 33015, 21263],
Anyone help me to solve this.. Thanks in advance
Do it like below:-
$final_array = array();
if(count($arr1)>=count($arr2)){
foreach ($arr1 as $arr){
$key='';
foreach ($arr2 as $ar2){
if($arr['isp'] == $ar2['isp']){
$final_array[$arr['isp']] = array($arr['isp'],$arr['sent_yest'],$ar2['sent_today']);
$key ='';break;
}else{
$key = $arr['isp'];
}
}
if($key!==''){
$final_array[$key] = array($arr['isp'],$arr['sent_yest'],0);
$key ='';
}
}
}
if(count($arr2)>count($arr1)){
foreach ($arr2 as $ar2){
$key='';
foreach ($arr1 as $arr){
if($ar2['isp'] == $arr['isp']){
$final_array[$ar2['isp']] = array($ar2['isp'],$arr['sent_yest'],$ar2['sent_today']);
$key ='';break;
}else{
$key = $ar2['isp'];
}
}
if($key!==''){
$final_array[$key] = array($ar2['isp'],0,$ar2['sent_today']);
$key ='';
}
}
}
echo "<pre/>";print_r($final_array);
Output:-https://eval.in/814625
I would avoid foreach if it's possible, since it leads to code that's much harder to understand. With array operation it can look like this:
// First we merge the two arrays
$merged = array_merge($data_yest, $data_today);
// Then format it
$final = array_reduce($merged, function($final, $item) {
// Initialize for each isp if it's not present
// This way we avoid overwriting previous data and have a default value 0
if (! isset($final[ $item['isp'] ])) {
$final[ $item['isp'] ] = [
'sent_yest' => 0,
'sent_today' => 0,
];
}
// And if one of the days is present, we add it
if (isset($item['sent_yest'])) {
$final[ $item['isp'] ][ 'sent_yest' ] = $item['sent_yest'];
}
if (isset($item['sent_today'])) {
$final[ $item['isp'] ][ 'sent_today' ] = $item['sent_today'];
}
// Then return the modified array
return $final;
}, []);
print_r($final);
exit;
Result looks like this:
Array
(
[aol] => Array
(
[sent_yest] => 46838
[sent_today] => 14135
)
[gmail] => Array
(
[sent_yest] => 33015
[sent_today] => 21263
)
[juno] => Array
(
[sent_yest] => 93544
[sent_today] => 74934
)
[roadrunner] => Array
(
[sent_yest] => 6181
[sent_today] => 939
)
[yahoo] => Array
(
[sent_yest] => 71444
[sent_today] => 22059
)
[att] => Array
(
[sent_yest] => 0
[sent_today] => 624
)
)

Parse a php array that has float index into new array

I have an array with float indexes that I'm getting from a plugin. I want to parse this array and take the ones that are float and put them in as a new array. Meaning what I have is
[1] => gsurvey128f54af2
[2] => gsurvey282bd4253
[5.1] => gsurvey5649a964f
[5.2] => gsurvey5fddb5e9f
[5.3] => gsurvey533c5b311
[5.4] => gsurvey5c8933efb
[5.5] => gsurvey5da48f59b
What I want is:
[1] => gsurvey128f54af2
[2] => gsurvey282bd4253
[5] => array (
[0] => gsurvey5649a964f
[1] => gsurvey5fddb5e9f
[2] => gsurvey533c5b311
[3] => gsurvey5c8933efb
[4] => gsurvey5da48f59b
)
I'm not clear on what's the best way to approach this.
I made the comment above that this problem is very prone to error because it is possible to have input that would set a single value to be both a string and an array at the same time. That will obviously fail. Assuming that the input is clean...
$new_array = array();
foreach($old_array as $key=>$val)
{
$a = explode('.', $key);
if(sizeof($a)==2)
{
if(!isset($new_array[$a[0]])) $new_array[$a[0]] = array();
$new_array[$a[0]][] = $val;
}
else $new_array[$key]=$val;
}
Example with array_walk:
$array = array (
'1' => 'gsurvey128f54af2',
'2' => 'gsurvey282bd4253',
'5.1' => 'gsurvey5649a964f',
'5.2' => 'gsurvey5fddb5e9f',
'5.3' => 'gsurvey533c5b311',
'5.4' => 'gsurvey5c8933efb',
'5.5' => 'gsurvey5da48f59b'
);
$output = array();
array_walk( $array, function( $item, $key ) use ( &$output ) {
$keys = explode( '.', $key );
isset( $keys[1] ) ? $output[ $keys[0] ][ $keys[1] ] = $item : $output[ $keys[0] ] = $item;
});
print_r( $output );
/*
Array
(
[1] => gsurvey128f54af2
[2] => gsurvey282bd4253
[5] => Array
(
[1] => gsurvey5649a964f
[2] => gsurvey5fddb5e9f
[3] => gsurvey533c5b311
[4] => gsurvey5c8933efb
[5] => gsurvey5da48f59b
)
)
*/
For this specific case, this should work:
foreach($array as $k => $v) {
if(count($i = explode('.', $k)) > 1) {
$result[$i[0]][] = $v;
} else {
$result[$k] = $v;
}
}

Combination of arrays

I have tried to get the below code to work for a good couple of hours, but just don't succeed.
I have this date array:
Array ( [0] => Array ( [0] => 2007 )
[1] => Array ( [0] => 2008 )
[2] => Array ( [0] => 2009 )
...
)
and this plusMinus one:
Array ( [0] => Array ( [plus] => 2 [date] => 2007 )
[1] => Array ( [minus] => 1 [date] => 2008 )
[2] => Array ( [minus] => 1 [date] => )
[3] => Array ( [plus] => 1 [date] => 2010 [minus] => 1 )
)
I have been trying to combine them into this:
Array ( [0] => Array ( [date] => 2007 [plus]=> 2)
[1] => Array ( [date] => 2008 [minus]=> 1)
[2] => Array ( [date] => 2009 [plusMinus]=> 0)
[3] => Array ( [date] => 2010 [plus] => 1 [minus]=>1 )
...
)
So basically I want to check if a value of the date array exists in the plusMinus array. If true the date and values from the plusMinus array shall replace the entry in the date array.
If false, the original date array entry is complemented by a [plusMinus] => 0 key-value pair.
The way I have tried to do it is this:
foreach ($filler as $key1 => $value1)
{
foreach ($plusMinus as $key2 => $value2)
{
if ($value1['0'] !== $value2['date'])
{
$value1['plusMinus'] = '0';
$result2[$key1][] = $value1;
}
elseif ($value1['0'] == $value2['date'])
{
if (array_key_exists('plus',$value2))
{
$value1['plus'] = $value2['plus'];
$result2[$key1][]=$value1;
}
elseif(array_key_exists('minus',$value2))
{
$value1['minus'] = $value2['minus'];
$result2[$key1][]=$value1;
}
elseif(array_key_exists('minus',$value2) &&
array_key_exists('plus',$value2))
{
}
}
}
}
$valuesComplete = array();
foreach ($result2 as $value) {
$result2 = $value['0'];
array_push($valuesIncomplete, $result2);
}
return $valuesComplete;
Instead of the desired outcome described above I get this:
Array ( [0] => Array
( [0] => 2007 [plus] => 2 )
[1] => Array ( [0] => 2008 [plusMinus => 0 )
[2] => Array ( [0] => 2009 [plusMinus] => 0 )
[3] => Array ( [0] => 2010 [plusMinus] => 0 )
[4] => Array ( [0] => 2011 [plusMinus] => 0 )
[5] => Array ( [0] => 2012 [plusMinus] => 0 )
[6] => Array ( [0] => 2013 [plusMinus] => 0 )
)
What am I missing? Thanks for any help!
Unfortunately, because of the input data format, I can't see any way to do this that doesn't involve an O(n + m + p) operation. But no matter, you gotta do what you gotta do.
Firstly I would start by filtering the useless elements from the PlusMinus array. Since it's already fairly close to the desired output format, it makes sense to use this as the base of the result.
$temp = array();
foreach ($plusMinus as $item) {
if (!empty($item['date'])) {
$temp[$item['date']] = $item;
}
}
Notice that I used the date as the index of the temporary array we're using to build the result. This is to allow you to easily ensure that the result array is in the correct order, and to quickly check whether an item needs to be added from the Filler array.
Next, we need to add any missing elements from the Filler array:
foreach ($filler as $item) {
if (!isset($temp[$item[0]])) {
$temp[$item[0]] = array(
'date' => $item[0],
'plusMinus' => 0
);
}
}
Now all the data is in the array in the correct format, we just need to sort it:
ksort($temp);
...and get convert it back to an indexed array:
return array_values($temp);
No need for the performance killing nested loops or complex flow control.
See it working
As I understood you need to add years that not in second array but in first?
In that case you can do:
foreach ($filler as $key1 => $value1)
{
$ok = false;
foreach ($plusMinus as $key2 => $value2)
{
if($value2['date']==$value1[0])
{
$ok = true;
break;
}
}
if(!$ok)
{
$plusMinus[$value1[0]]=array('date'=>$value1[0], 'plusMinus'=>0);
}
}
<?php
$a1 = array(array( 2007 ),
array( 2008 )
);
$a2 = array(array('plus'=>1, 'date'=>2007),
array('minus'=>1,'date'=>2008),
array('plus'=>1, 'minus'=>1, 'date'=>2008)
);
$r = array();
foreach($a1 as $k1=>$d1) {
$year = $d1[0];
foreach( $a2 as $k2=>$d2 ) {
if( $d2['date'] == $year ) {
$r[$year]['date'] = $year;
if(isset($d2['plus'])) {
$r[$year]['plus'] = $d2['plus'];
}
if(isset($d2['minus'])) {
$r[$year]['minus'] = $d2['minus'];
}
}
}
}
print_r($r);
and result
Array
(
[2007] => Array
(
[date] => 2007
[plus] => 1
)
[2008] => Array
(
[date] => 2008
[minus] => 1
[plus] => 1
)
)
$ar1 = array( array(2007), array(2008), array(2009), array(2010) );
$ar2 = array(
array("date"=>2007, "plus"=>2),
array("date"=>2008, "minus"=>1),
array("date"=>"", "minus"=>1),
array("date"=>2010, "plus"=>1, "minus"=>1)
);
foreach($ar2 as $key=>$val){
if(isset($ar1[$key][0]))
$val["date"] = $ar1[$key][0];
$ar2[$key] = $val;
}
I am not sure if I understand you correctly but this works fine...
It will work only if you are sure that your both arrays "date" equals one to other..
This is what I came up with:
To not create the product of both arrays (foreach inside foreach), I first index the $plusMinus array with the date. That will allow to test quickly if a year exists or not:
$years = array_combine(array_column($plusMinus, 'date'), $plusMinus);
This uses the array_column() function of PHP 5.5, if you don't have it you can easily create it your own.
After doing that it is exactly how you wrote it in your own words:
foreach($date as &$entry)
{
list($year) = $entry;
$entry = array('date' => $year);
// check if a value of the date array exists in the plusMinus array.
if (isset($years[$year])) {
// If true the date and values from the plusMinus array shall replace the entry in the date array
$entry += $years[$year];
} else {
// If false, the original date array entry is complemented by a [plusMinus] => 0 key-value pair.
$entry += array('plusMinus' => 0);
}
}
unset($entry);
See it i action.
This will work just fine.
I did not at all understand your question, but if i got it this is the way:
First make your $datearray more understandable like this:
$dateArray = array(2007,2008,2009,2010);
$plusMinus = array(
array( 'plus' => 2 ,'date' => 2007),
array( 'minus' => 1 ,'date' => 2008),
array ( 'minus' => 1 , 'date' => '' ),
array ( 'plus' => 1 , 'date' => 2010 , 'minus' => 1 )
);
You can make it multidimensional later;
After that:
foreach($dateArray as $k=>$v)
{
if(in_array($v,$plusMinus[$k]))
{
$filler[$k] = $plusMinus[$k];
}
else{
if(empty($plusMinus[$k]['date']))
{
$filler[$k]['date']= $v;
$filler[$k]['plusMinus'] = 0;
}
}
}
This is simple and clean, understandable way with very little code if your arrays will always have the structure you described, meaning the plusMinus values for 2007 are in the cell [0] and the 2007 in the dateArrays is also in the cell [0] like you have shown. I hope i could help.

Grouping multidimensional array by two values

I have arrays like this.
[11] => Array
(
[transactioncurrencyid] => Array
(
[!name] => US Dollar
[!] => {041E3DC9-D938-DD11-982C-0013724C58B7}
)
[smi_processingmonth] => Array
(
[!date] => 6/1/2011
[!time] => 2:27 PM
[!] => 2011-06-01T14:27:00-07:00
)
[smi_cchistoryid] => {678C5036-9EAA-E111-88E0-00155D010302}
[smi_includeindeal] => Array
(
[!name] => No
[!] => 0
)
[smi_locationid] => Array
(
[!name] => 1134 Hooksett Rd
[!] => {5CC1585B-91AA-E111-88E0-00155D010302}
)
)
[12] => Array
(
[transactioncurrencyid] => Array
(
[!name] => US Dollar
[!] => {041E3DC9-D938-DD11-982C-0013724C58B7}
)
[smi_processingmonth] => Array
(
[!date] => 5/1/2011
[!time] => 2:27 PM
[!] => 2011-05-01T14:27:00-07:00
)
[smi_cchistoryid] => {688C5036-9EAA-E111-88E0-00155D010302}
[smi_includeindeal] => Array
(
[!name] => No
[!] => 0
)
[smi_locationid] => Array
(
[!name] => 1134 Hooksett Rd
[!] => {5CC1585B-91AA-E111-88E0-00155D010302}
)
)
How can i group them by location id then by smi_processingmonth
So I get something like this
[1134 Hooksett Rd] => Array
(
[ 5/1/2011] = array(
[transactioncurrencyid] => Array
(
[!name] => US Dollar
[!] => {041E3DC9-D938-DD11-982C-0013724C58B7}
)
[smi_processingmonth] => Array
(
[!date] => 5/1/2011
[!time] => 2:27 PM
[!] => 2011-05-01T14:27:00-07:00
)
[smi_cchistoryid] => {688C5036-9EAA-E111-88E0-00155D010302}
[smi_includeindeal] => Array
(
[!name] => No
[!] => 0
)
[smi_locationid] => Array
(
[!name] => 1134 Hooksett Rd
[!] => {5CC1585B-91AA-E111-88E0-00155D010302}
)
)
[1/1/2011] = array(
[transactioncurrencyid] => Array
(
[!name] => US Dollar
[!] => {041E3DC9-D938-DD11-982C-0013724C58B7}
)
[smi_processingmonth] => Array
(
[!date] => 6/1/2011
[!time] => 2:27 PM
[!] => 2011-06-01T14:27:00-07:00
)
[smi_cchistoryid] => {678C5036-9EAA-E111-88E0-00155D010302}
[smi_includeindeal] => Array
(
[!name] => No
[!] => 0
)
[smi_locationid] => Array
(
[!name] => 1134 Hooksett Rd
[!] => {5CC1585B-91AA-E111-88E0-00155D010302}
)
)
)
I have tried
foreach($array as $keys)
{
$key = $keys['smi_processingmonth']['!date'];;
if (!isset($groups[$key]))
{
$groups[$key] = array($keys);
} else {
$groups[$key][] = $keys;
}
}
$newGroups = array();
if(is_array($groups))
{
foreach($groups as $cats => $values)
{
foreach($values as $itemValues){
$st = rtrim(trim($itemValues['smi_locationid']['!']));
$key = $st;
if (!isset($newGroups[$key]))
{
$newGroups[$key] = array($groups);
} else {
$newGroups[$key][] = $itemValues;
}
}
}
}
Thanks!
Taking from Johan with a few modifications:
avoid ltrim if already using trim
put in a function, I can use temporary variables to maintain readability
add a final [], to avoid nasty $name/$date collision, out of original request, but safer
function compactArray($data)
{
$new_structure = array();
foreach ( $data as $row )
{
$name = trim($row['smi_locationid']['!name']);
$date = trim($row['smi_processingmonth']['!date']);
$new_structure[ $name ][ $date ][] = $row;
}
return $new_structure;
}
Ehm, i have not tested it. But isn't it just:
$new_structure = array();
foreach ( $data as $row ) {
$key1 = rtrim(trim($row['smi_locationid']['!name']));
$key2 = rtrim(trim($row['smi_processingmonth']['!date']));
$new_structure[$key1][$key2] = $row;
}
This code could use some isset()s, but i decided to keep them out for clarity.
The following produces your desired output array, correctly sorted:
function transaction_datecmp($tran1, $tran2)
{
return strtotime($tran1['smi_processingmonth']['!']) -
strtotime($tran2['smi_processingmonth']['!']);
}
$output_arr = array();
foreach ($input_arr as $transaction) {
$location = $transaction['smi_locationid'] ['!name'];
$date = $transaction['smi_processingmonth']['!date'];
$output_arr[$location][$date] = $transaction;
}
ksort($output_arr); // sorts by location
foreach ($output_arr as &$transaction_arr) {
uasort($transaction_arr, 'transaction_datecmp');
}
Your data structure relies on the assumption that there cannot be two transactions on the same day, which is a somewhat dangerous assumption. Also using a location as a key is far from ideal (because of spelling, location changes, etc.) - unless it really should group things, like for paper mailing.
Data cleanup, like trimming strings, should be done beforehand, ideally at data input time.

Categories