Grouping multidimensional array by two values - php

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.

Related

PHP - How do I unset an array index by value inside that index

I have an array of objects ($response) that looks like this:
Array
(
[0] => stdClass Object
(
[CardNumber] => 5897853070424xxx
[CardHolderName] => P Stoltz
[CardHolderContactNumber] =>
[CardHolderEmailAddress] =>
[CardExpiryDate] => 2017-09-01T00:00:00
[CardHolderTypeID] => 2
[LastUsedDate] => 2017-05-25T00:00:00
)
[1] => stdClass Object
(
[CardNumber] => 589785304326xxx
[CardHolderName] => J Stoltz
[CardHolderContactNumber] =>
[CardHolderEmailAddress] =>
[CardExpiryDate] => 2017-09-01T00:00:00
[CardHolderTypeID] => 2
[LastUsedDate] => 2017-05-25T00:00:00
)
)
Now, I need to unset the entire object where CardNumber != '589785304326xxx'
I have tried this:
$cardnumber = '5897853070424xxx';
foreach( $response as $res )
{
if($res->CardNumber != $cardnumber)
{
unset($res);
}
}
This does nothing. Any suggestions?
What you have tried will only unset the current object in the loop. You need to do the following:
foreach($response as $key => $res) {
if($res->CardNumber != $cardnumber) {
unset($response[$key], $res);
continue;
}
}
Use unset() inside the loop.
eg:
unset('key value', 'your array name');

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
)
)

group php array by subarray value

I want to group an array by a subarray's value. If I have an array like this:
Array
(
[0] => Array
(
[userID] => 591407753
[propertyA] => 'text1'
[propertyB] => 205
)
[1] => Array
(
[userID] => 989201004
[propertyA] =>'text2'
[propertyB] => 1407
)
[2] => Array
(
[userID] => 989201004
[propertyA] => 'text3'
[propertyB] => 1407
)
)
I want to sort to group this array by a subarray's value so I can have an array like this:
Array
(
[0]=>Array
(
[userID]=>59140775
[properties]=>Array
(
[0]=>text1
)
[propertyB]=>205
)
[1]=>Array
(
[userID]=>989201004
[properties]=>Array
(
[0]=>'text2'
[1]=>'text3'
)
[propertyB]=>1047
)
)
How can I make this?
Before I had tried this:
$result = array();
foreach ($userArray as $record)
{
$id=$record['userID'];
if(isset($result[$id]))
{
$result[$id]['propertyA'][]=array($record['propertyA']);
}
else {
$record["propertyA"]=array($record['propertyA']);
unset($record['tweet']);
$result[$id]=$record;
}
}
the problem was for the propertyA. I was an the result an additional property propertyA with the table like this:
Array
(
[0]=>Array (
[userID]=>989201004
[propertyA]=>'text2'
[properties]=>Array(
[0]=>'text2'
[1]=>'text3'
)
)
)
The following code should do the job. I hope it is self-explanatory:
$result = array();
foreach ($array as $record) {
if (!isset($result[$record['userID']])) {
$result[$record['userID']] = array(
'userID' => $record['userID'],
'properties' => array($record['propertyA']),
'propertyB' => $record['propertyB'],
);
}
else {
$result[$record['userID']]['properties'][] = $record['propertyA'];
}
}
$result = array_values($result);

Append a new array to an existing array

I am using Codeigniter Sessions to build a "Betslip".
I am adding the team name and odds to the bet slip and then plan to loop through each "bet" element to create a betslip.
The ideal array needs to look like :
[betslip] => Array
(
[bet] => Array
(
[team] => Rayo Vallecano
[odds] => 67/100
)
[bet] => Array
(
[team] => Elche
[odds] => 1/100
)
)
However in my code, I just seem to be overwriting what is already there.
My current PHP code is as follows :
// Get Team Name
$teamname = $this->uri->segment(3);
// Get Odds
$odds1 = $this->uri->segment(4);
$odds2 = $this->uri->segment(5);
$odds = $odds1;
$odds .= "/";
$odds .= $odds2;
// Build An array titled Bet
$bet = array(
'bet' => array(
'team' => urldecode($teamname),
'odds' => $odds
)
);
$betslip = $this->session->userdata('betslip');
// Create The Betslip For The First Time...
if(empty($betslip))
{
$this->session->set_userdata('betslip', $bet);
}
else
{
// Add To The Betslip Array...
$betslip['bet'] = array(
'team' => urldecode($teamname),
'odds' => $odds
);
$this->session->set_userdata('betslip', $betslip);
}
How do I just append a bet to the existing bet slip array?
Is it possible to have multiple array keys with the same name too?
Thanks in advance..
This is not an ideal array
[betslip] => Array
(
[bet] => Array
(
[team] => Rayo Vallecano
[odds] => 67/100
)
[bet] => Array
(
[team] => Elche
[odds] => 1/100
)
)
it should be like
[betslip] => Array
(
[0] => Array
(
[team] => Rayo Vallecano
[odds] => 67/100
)
[1] => Array
(
[team] => Elche
[odds] => 1/100
)
)
<?php
$item = array();
$item2 = array(
'team' => 1,
'odds' => "1/100"
);
for ($x = 0; $x <= 10; $x++) {
$item[] = $item2;
}
print_r($item);
?>

Grouping items in assoc. array

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
)
)

Categories