2

我正在生成一个虚拟数组,其中键是时间戳,值是零。开始是今天(没有时间部分的日期)并返回$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
4

2 回答 2

1

作为一种解决方法,您可以使用 格式的字符串键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()很好地提供了非常简洁的代码,但如果你真的要处理大量数据,我希望这种类型的解决方案会是最有效的。(基准以找出答案。)

于 2012-05-30T00:29:51.473 回答
0

那是因为+(应用于数组)从右侧数组中追加了左侧数组中不存在的数据。

您使用var_dump($reals + $dummy);了 which 意味着:取$reals其中包含 1 个项目(今天作为第一个也是唯一的元素)并附加所有$dummy具有另一个键的内容。

可能的解决方案是:

  1. 对数据进行排序(你提到过)
  2. 手动合并,与foreach
于 2012-05-30T00:24:16.383 回答