1

Here's what I'm doing:

$dateRange = array('2010-01-01', '2010-01-02', '2010-01-03', ...);
$data = array('2010-01-01' => 5, '2010-01-03' => 7);

foreach ($dateRange as $date) {
    $values[$date] = $data[$date];
}

$values results in:

array (
    '2010-01-01' => 5
    '2010-01-02' => null
    '2010-01-03' => 7
    ...
)

Seems fairly efficient, but I wonder if there's a simple PHP function that'll handle this.

0

3 Answers 3

9
$values = array_merge(array_fill_keys($dateRange, null), $data);

Whether that's really any more efficient can only be found out through testing, but I'd say it's more concise, easy to understand, and it doesn't throw errors for non-existent keys in $data. :)

Sign up to request clarification or add additional context in comments.

4 Comments

You should switch the order of your arguments, see the docs: "If an array key exists in both arrays, then the element from the first array will be used and the matching key's element from the second array will be ignored." However, array_merge will renumber your keys as soon as it "considers" them numeric. So I would recommend using the + operator instead of array_merge, because it is a lot more predictable. This also preserves values from the first operand when the key exists in the second. Use: $data + array_fill_keys($dateRange, null) or: array_merge($data, array_fill_keys($dateRange, null)
@ontrack I don't know which docs you're reading, but array_merge says: If the input arrays have the same string keys, then the later value for that key will overwrite the previous one. I'm using array_merge daily, and this is how it works. Also, these are clearly string keys, not numeric keys.
My quote came from Example #3, I seem to have missed the top of the doc. But that quote is actually specifically about the + operator The reason why (I prefer) the operator is because the behaviour changes as soon as you start to use numeric keys. Ergo: It currently works as expected but stops working in a seemingly similar situation. Something I try to avoid specifically because it advocates bugs. Maybe you want to start using something similar with day-numbers.
@ontrack There's also something to be said about array_merge keeping the sort order intact though. :) You have a point about changing the keys to day numbers, but at that point it'd submit you're talking about a completely different script and would need to reevaluate every operation you're doing on the array anyway. There's no need to go out of your way to make sure your script is internally future-proof. ;) So, just for the record: $values = $data + array_fill_keys($dateRange, null) should work the same, except for the order of the result.
1

There's array_merge but it will produce 1 => 2010-01-02 instead of 2010-01-02 => null.

There are also a whole host of array functions at http://us.php.net/manual/en/ref.array.php

[Edit]: Leaving this answer because of the links, but the other answer accomplishes exactly what you wanted.

1 Comment

These vague/indirect insights are better posted as a comment under the question, IMO. It's rather Not An Answer in my opinion because it doesn't provide a solution and merely references the documentation.
0

To populate the desired associative array in a single pass, you can use array_reduce() and fallback to null values when a date doesn't have a related value in $data. Because this associative array doesn't have numeric keys, the union operator can be used to add new elements to the result array. Demo

var_export(
    array_reduce(
        $dateRange,
        fn($result, $date) => $result + [$date => $data[$date] ?? null],
        []
    )
);

Or another way it to combine the dates array with the null coalesced array. Demo

var_export(
    array_combine(
        $dateRange,
        array_map(fn($date) => $data[$date] ?? null, $dateRange)
    )    
);

There's also nothing unprofessional about using a classic loop, just make sure to null coalesce to avoid Warnings. Demo

$result = [];
foreach ($dateRange as $date) {
    $result[$date] = $data[$date] ?? null;
}
var_export($result);

Comments

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.