我正在生成一个虚拟数组,其中键是时间戳,值是零。开始是今天(没有时间部分的日期),并返回过去 $days
天:
$days = 10;
$limit = strtotime(date('Y-m-d'));
$start = $limit - (($days - 1) * 86400);
// Dummy array of timestamps and zeroes
$dummy = array_combine(range($start, $limit, 86400), array_fill(0, $days, 0));
var_dump($dummy);
array (size=10)
1337551200 => int 0
1337637600 => int 0
1337724000 => int 0
1337810400 => int 0
1337896800 => int 0
1337983200 => int 0
1338069600 => int 0
1338156000 => int 0
1338242400 => int 0
1338328800 => int 0 // Today is the last
这个数组将与另一个从MySQL结果集中提取的数组合并(它的值应该覆盖虚拟值):
$keys = array_map(function($e) { return strtotime($e['date']); }, $values);
$vals = array_map(function($e) { return intval($e['count']); }, $values);
// Array of real values coming from database
$reals = array_combine($keys, $vals);
var_dump($reals);
array (size=1)
1338328800 => int 2 // Today
由于array_merge
操作键重新排序(当键类型integer
时),我切换到数组运算符+
并且生成的数组被重新排序:新键排在第一位:
var_dump($reals + $dummy);
array (size=10)
1338328800 => int 2 // Today become the first
1337551200 => int 0
1337637600 => int 0
1337724000 => int 0
1337810400 => int 0
1337896800 => int 0
1337983200 => int 0
1338069600 => int 0
1338156000 => int 0
1338242400 => int 0
所以问题是+
运算符将这些键放在第一位,如何在不使用排序函数的情况下解决这个问题,如下所示:
$merged = $reals + $dummy;
ksort($merged);
var_dump($merged);
array (size=10)
1337551200 => int 0
1337637600 => int 0
1337724000 => int 0
1337810400 => int 0
1337896800 => int 0
1337983200 => int 0
1338069600 => int 0
1338156000 => int 0
1338242400 => int 0
1338328800 => int 2
作为一种解决方法,您可以使用 YYYY-MM-DD
格式的字符串键来防止array_merge()
重新编制索引。它也比时间戳更具描述性。您可以使用DatePeriod
轻松创建密钥。
如果您正在寻找最佳解决方案,我会做这样的事情:
# begin timestamp
$ts = 1337551200;
# values from database
$values = [
['date' => '2012-05-23', 'count' => 42],
['date' => '2012-05-26', 'count' => 666]
];
# holds the key=>val pairs
$data = [];
foreach ($values as $value)
{
$value_ts = strtotime($value['date']);
# backfill all missing dates
for ($missing_ts = $ts; $missing_ts < $value_ts; $missing_ts += 86400)
$data[$missing_ts] = 0;
# add date from database
$data[$value_ts] = $value['count'];
$ts = $value_ts + 86400;
}
# append all remaining dates
for ($now = time(); $ts <= $now; $ts += 86400)
$data[$ts] = 0;
这只对数据库中的数据进行一次迭代,并插入值为 0 的缺失键。它仅在$values
已经排序时才有效,并且它取决于相隔 86400 秒的天数(就像您的原始解决方案一样)。
它可能还没有准备好"复制粘贴",但它应该让您了解如何以最小的开销实现一次性解决方案。像array_map()
这样的函数非常适合提供非常简洁的代码,但如果你真的要处理大量数据,我希望这种类型的解决方案将是快速的。(基准测试找出答案。
这是因为+
(应用于数组)附加了右侧数组中不存在的左侧数组中的数据。
您已经使用了var_dump($reals + $dummy);
这意味着:取$reals
,它由 1 个项目组成(今天作为第一个也是唯一的元素),并从具有另一个键的$dummy
附加所有内容。
可能的解决方案是:
- 对数据进行排序(您提到过)
- 手动合并,
foreach