【问题标题】:The best way to break generator into chunks将生成器分成块的最佳方法
【发布时间】:2015-11-16 08:19:15
【问题描述】:

你能帮我写这段代码,将生成器产量分成 100 个块,并将它们保存到数据库中更漂亮。

$batchSize = 100;

$batch = [];
$i = 0;

/** 
 * @yield array $item
 */
foreach(itemsGenerator() as $item) {
    $batch[] = $item;
    $i++;

    if ($i === $batchSize) {
        Db::table('items')->save($batch);

        $batch = [];
        $i = 0;
    }

    $cnt++;
}

if ($batch) {
     Db::table('items')->save($batch);
}

我不想把分块的逻辑放在itemsGenerator里

【问题讨论】:

  • 或许更适合 codereview.stackexchange.com

标签: php foreach generator chunks


【解决方案1】:

您可以将块逻辑放入一个单独的可重用函数中。

解决方案 1:每个块都是一个生成器。

https://3v4l.org/3eSQm

function chunk(\Generator $generator, $n) {
    for ($i = 0; $generator->valid() && $i < $n; $generator->next(), ++$i) {
        yield $generator->current();
    }
}

function foo() {
  for ($i = 0; $i < 11; ++$i) {
    yield $i;
  }
}

for ($gen = foo(); $gen->valid();) {
    $chunk = [];
    foreach (chunk($gen, 3) as $value) {
        $chunk[] = $value;
    }
    print json_encode($chunk) . "\n";
}

解决方案 2:每个块都是一个数组。

https://3v4l.org/aSfeR

function generator_chunks(\Generator $generator, $max_chunk_size) {
  $chunk = [];
  foreach ($generator as $item) {
    $chunk[] = $item;
    // @todo A local variable might be faster than count(), but adds clutter to the code. So using count() for this example code.
    if (count($chunk) >= $max_chunk_size) {
      yield $chunk;
      $chunk = [];
    }
  }
  if ([] !== $chunk) {
      // Remaining chunk with fewer items.
      yield $chunk;
  }
}

function generator() {
    for ($i = 0; $i < 11; ++$i) {
        yield $i;
    }
}

foreach (generator_chunks(generator(), 3) as $chunk) {
    print json_encode($chunk) . "\n";
}

现在所有一个块将作为一个数组同时在内存中,而不是整个序列。

可能有一些方法可以让每个块表现得像一个生成器。但这是另一回事。

【讨论】:

    猜你喜欢
    • 2011-12-25
    • 2015-07-16
    • 1970-01-01
    • 2010-11-12
    • 2014-06-26
    • 2011-05-18
    • 2013-09-26
    • 2011-04-20
    • 1970-01-01
    相关资源
    最近更新 更多