1

I have this object thrown by an API and I would like to recreate it into a new array and combine the time value of each element that has the same date value

Array (
    [0] => Array (
            [id] => 6
            [time] => morning
            [date] => 2015-09-29
        )

    [1] => Array (
            [id] => 5
            [time] => night
            [date] => 2015-09-29 
        )
    [2] => Array 
            [id] => 31
            [time] => morning
            [date] => 2015-12-07 
        )

    [3] => Array
            [id] => 3
            [time] => night
            [date] => 2015-11-15
        )

)

I have this php code, but its not working properly, second element with the same date won't add the time value on existing key and I'm not sure how to properly set the $full variable

$date = array();
foreach( $datas as $data) { 

    $full = count(  $data['time'] ) > 1 ? true : false;
    $dates[$data['date']] = array(
        'date' => $data['date'],
        'fully_book' => $full,    
        'time' => array( $data['time']  ),
    ); 
}

The result I really wanted to get is something like this,

array(
        [2015-09-29] => array(
            [date] => 2015-09-29
            [fully_book] => true,
            [time] => array(
                  [0] => morning,
                  [1] => night
            )
        ),
        [2015-12-07] = array(
            [date] => 2015-09-29,
            [fully_book] => false,
            [time] => array(
                  [0] => night
            )
        ),
        [2015-11-15] = array(
            [date] => 2015-11-15,
            [fully_book] => false,
            [time] => array(
                  [0] => morning
            )
    )

Would appreciate any help,

Thanks

5
  • becuse you use the date as the key and you cant have duplicate keys in an array Commented Sep 8, 2015 at 20:46
  • just edited my question, I know that and wanted to combine time value if date is the same Commented Sep 8, 2015 at 20:47
  • 1
    in the loop check if the key exists, if yes add, else create new Commented Sep 8, 2015 at 20:49
  • I actually tried having $newdata = array( 'time' => $data['time'], ); if ( array_key_exists($data['date'], $date) ) { array_push($data['date'], $newdata); } but it just messing up, I don't even know if array_key_exists and array_push be an option Commented Sep 8, 2015 at 20:56
  • Will time values always be morning/night, and only one of each per date? Commented Sep 8, 2015 at 21:07

4 Answers 4

2

Augment the time index while you're in your foreach loop:

$date = array();
foreach($datas as $data) { 
    $date[$data['date']]['date'] = $data['date']; //I'm not entirely sure why you need this. You might consider just relying on the key.  
    $date[$data['date']]['time'][] = $data['time'];
    $full = count($date[$data['date']]['time']) > 1 ? true : false;  
    $date[$data['date']]['fully_book'] = $full;

}

var_dump($date); //see below.

Duplicate entries will overwrite the previous entry, but that's alright because those fields are identical. Any time a new data['time'] is processed, it will be added.

$full now counts the number of elements in the $data['time'] after $data['time'] has been added and will add true once there are more than 1 time provided.

The above outputs the following:

array(3) {
  ["2015-09-29"]=>
  array(3) {
    ["date"]=>
    string(10) "2015-09-29"
    ["time"]=>
    array(2) {
      [0]=>
      string(7) "morning"
      [1]=>
      string(5) "night"
    }
    ["fully_book"]=>
    bool(true)
  }
  ["2015-12-07"]=>
  array(3) {
    ["date"]=>
    string(10) "2015-12-07"
    ["time"]=>
    array(1) {
      [0]=>
      string(7) "morning"
    }
    ["fully_book"]=>
    bool(false)
  }
  ["2015-11-15"]=>
  array(3) {
    ["date"]=>
    string(10) "2015-11-15"
    ["time"]=>
    array(1) {
      [0]=>
      string(5) "night"
    }
    ["fully_book"]=>
    bool(false)
  }
}
Sign up to request clarification or add additional context in comments.

5 Comments

Your code does not work. Look at the 1st array, it is still ["fully_book"]=> bool(false) even though ["time"]=> array(2).... Your $full = count($data['time']) > 1 ? true : false; is not doing what you think it is.
@Sean, that was provided by OP and I assumed (apparently incorrectly) that it was working as intended as the question seems focused on augmenting time. I'll take another look.
it was part of the OP's original question "....and I'm not sure how to properly set the $full variable"
@Sean, Yikes! You're totally right. I've updated my answer to reflect $full being set (and setting '$date['fully_book'] correctly.
Thank you, your idea works perfectly, The API actually throws different datas, but I got it working now, Thanks again
2

This should be simpler. This way the only thing you have to check is the count of times.

foreach( $datas as $data) {
    //set the date (overwrites each time for repeated dates)
    $date[$data['date']]['date'] = $data['date'];
    $date[$data['date']]['time'][] = $data['time'];  //add the time
    // after the time has been added you can check the number of times
    $date[$data['date']]['fully_book'] = count($date[$data['date']]['time']) > 1;
}

1 Comment

awesome, I never realize it was this simple, I even try hard testing with array_key_check and array_push, I just simply hate arrays..lol
0

Create a empty array loop the array set empty array key to date like this empty_array[val[date]] = array ( 'date'=>val[date] ,..)

Comments

0

An O(n) solution

I think this "could" be faster if we did some sort of sort (but then it would create a quasi-linear), but couldn't figure out any way to make it faster. Never mind, fastest is O(n), since we need to insert all keys and values anyways. I made the code a bit more complicated (since what you gave us may not necessarily always be the same input (for example time may not always be so simple as morning/night). First, a bit of syntax reformatting to get the array created by PHP

<?php
$array = array(
    0 => array(
            'id' => 6,
            'time' => 'morning',
            'date' => '2015-09-29'
        ),
    1 => array(
            'id' => 5,
            'time' => 'night',
            'date' => '2015-09-29'
        ),
    2 => array(
            'id' => 31,
            'time' => 'morning',
            'date' => '2015-12-07'
        ),
    3 => array(
            'id' => 3,
            'time' => 'night',
            'date' => '2015-11-15'
        )
);

Iterating through array to find duplicates

Now that the array is constructed, we will iterate through the entire array. Since dates are stored as keys in our output array, and we know that we must have all the possible dates as keys, we can attempt to store a key for every iteration, if one already exists, that means that there is already some "date" value in the date slot. Usually we wouldn't need to check if it was morning or night because the moment there is some date set (and based on the arrays you've given us), the only possibility is that it was morning if the current one is night or vica versa, but for sake of brevity, we will check:

$output = array();
foreach ($array as $val) {
    if (!isset($output[$val['date']])) {
        $output[$val['date']] = array(
            'date' => $val['date'],
            'fully_book' => false, //By default since the key never existed
            'time' => array(
                $val['time']
            )
        );
    }
    else {
        if ($output[$val['date']]['time'][0] != $val['time']) {
            //A single mismatch means that this date must be fully booked since there is only morning or night
            $output[$val['time']][] = $val['time'];
            $output[$val['date']]['fully_booked'] = true;
        }
    }
}
print_r($output);
//Outputs: Array ( [2015-09-29] => Array ( [date] => 2015-09-29 [fully_book] => [time] => Array ( [0] => morning ) [fully_booked] => 1 ) [night] => Array ( [0] => night ) [2015-12-07] => Array ( [date] => 2015-12-07 [fully_book] => [time] => Array ( [0] => morning ) ) [2015-11-15] => Array ( [date] => 2015-11-15 [fully_book] => [time] => Array ( [0] => night ) ) )

This outputs a nicely created array with dates as keys and all the duplicates and other relevant information in the array output you specified in the answer. You can change things up (since the foreach loop is pretty flexible) in case you need other types of data input.

tl;dr and full code:

You can test this on PHPFiddle

<?php
$array = array(
    0 => array(
            'id' => 6,
            'time' => 'morning',
            'date' => '2015-09-29'
        ),
    1 => array(
            'id' => 5,
            'time' => 'night',
            'date' => '2015-09-29'
        ),
    2 => array(
            'id' => 31,
            'time' => 'morning',
            'date' => '2015-12-07'
        ),
    3 => array(
            'id' => 3,
            'time' => 'night',
            'date' => '2015-11-15'
        )
);
$output = array();
foreach ($array as $val) {
    if (!isset($output[$val['date']])) {
        $output[$val['date']] = array(
            'date' => $val['date'],
            'fully_book' => false, //By default since the key never existed
            'time' => array(
                $val['time']
            )
        );
    }
    else {
        if ($output[$val['date']]['time'][0] != $val['time']) {
            //A single mismatch means that this date must be fully booked since there is only morning or night
            $output[$val['time']][] = $val['time'];
            $output[$val['date']]['fully_booked'] = true;
        }
    }
}
print_r($output);
?>

1 Comment

Thank you for your answer, the If conditional checking was the first approached I attempted, I ended up having almost 100 lines using conditional and time value won't still combine, I'll test your code as it looks interesting, though answers above works perfectly, but I really love conditionals lol Thanks for the explanation also. appreciate it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.