0

I need your help. I want to prepare some data from a multidimensional array of objects to equal with the ChartJS data structure:

https://www.chartjs.org/docs/master/general/data-structures/

So for example this array here:

$source = [
    [
        'id'           => '123',
        'date_created' => '2020-10-19 22:50:46'
    ],
    [
        'id'           => '456',
        'date_created' => '2020-10-19 13:50:19'
    ],
    [
        'id'           => '276',
        'date_created' => '2020-09-19 11:50:46'
    ],
    [
        'id'           => '846',
        'date_created' => '2020-09-19 21:50:46'
    ],
    [
        'id'           => '543',
        'date_created' => '2020-10-18 22:50:46'
    ]
];

needs to be transformed to:

$dest = [
    '2020-10-19' => '2',
    '2020-09-19' => '2',
    '2020-10-18' => '1'
];

So logically the functions needs to count the occurrence of timestamps in an array only by the date (not the time). After that a new array must be created with the date as key and the occurrences of it as a value.

I've tried using this:

error_log( print_r( array_count_values( array_flip( array_column( $source, 'date_exported' ) ) ), true ) );

But this only returns an array of the occurrences of the columns. So how can I deal with this the right way?

2 Answers 2

2

Try this.

<?php

// Your input array.
$source = [
    [
        'id'           => '123',
        'date_created' => '2020-10-19 22:50:46'
    ],
    [
        'id'           => '456',
        'date_created' => '2020-10-19 13:50:19'
    ],
    [
        'id'           => '276',
        'date_created' => '2020-09-19 11:50:46'
    ],
    [
        'id'           => '846',
        'date_created' => '2020-09-19 21:50:46'
    ],
    [
        'id'           => '543',
        'date_created' => '2020-10-18 22:50:46'
    ]
];

// Output array.
$output = [];

// Loop over each element and extract its key.
foreach ($source as $element)
{
    // Turn date string into DateTime object.
    $dateTime = new DateTime($element['date_created']);
    // Get the intended key in Y-m-d format.
    $key = $dateTime->format('Y-m-d'); 
    
    // New key? Initialize to 1.
    if (!isset($output[$key]))
        $output[$key] = 1;
    else
        // Existing key, increment.
        $output[$key]++;
}

var_dump($output);
/*
array(3) {
  ["2020-10-19"]=>
  int(2)
  ["2020-09-19"]=>
  int(2)
  ["2020-10-18"]=>
  int(1)
}
*/

OR

// Output array.
$output = [];

foreach ($source as $element)
{
    $key = explode(' ', $element['date_created'])[0];
    if (isset($output[$key]))
        $output[$key]++;
    else
        $output[$key] = 1;
}

var_dump($output);
/*
array(3) {
  ["2020-10-19"]=>
  int(2)
  ["2020-09-19"]=>
  int(2)
  ["2020-10-18"]=>
  int(1)
}
*/

OR, as a one liner:

// Output array.
$output = [];

var_dump(array_count_values(array_map(function ($element) { return explode(' ', $element)[0]; }, array_column($source, 'date_created'))));
/*
array(3) {
  ["2020-10-19"]=>
  int(2)
  ["2020-09-19"]=>
  int(2)
  ["2020-10-18"]=>
  int(1)
}
*/
Sign up to request clarification or add additional context in comments.

Comments

1

If you map the array and explode on a space, then you can array_count_values:

$result = array_count_values(array_map(function($v) {
                                           return explode(' ', $v['date_created'])[0];
                                       }, $source));

Obviously there are functions to work with dates, but given this format it is shorter than converting to a timestamp and then formatting it as a date.

However, if this is coming from a database, then it may be better to just select COUNT on the data part.

2 Comments

So basically my last answer ;).
@RoAchterberg, basically, minus the unneeded array_column.

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.