Это поздний ответ на эту тему, но вот метод, который не использует временное хранилище:
public static class EnumerableExt
{
public static IEnumerable<IEnumerable<T>> Partition<T>(this IEnumerable<T> input, int blockSize)
{
var enumerator = input.GetEnumerator();
while (enumerator.MoveNext())
{
yield return nextPartition(enumerator, blockSize);
}
}
private static IEnumerable<T> nextPartition<T>(IEnumerator<T> enumerator, int blockSize)
{
do
{
yield return enumerator.Current;
}
while (--blockSize > 0 && enumerator.MoveNext());
}
}
И некоторый тестовый код:
class Program
{
static void Main(string[] args)
{
var someNumbers = Enumerable.Range(0, 10000);
foreach (var block in someNumbers.Partition(100))
{
Console.WriteLine("\nStart of block.");
foreach (int number in block)
{
Console.Write(number);
Console.Write(" ");
}
}
Console.WriteLine("\nDone.");
Console.ReadLine();
}
}
Вы близко ...
Почему элемент имеет значение 'item3'? Разве цикл for не заканчивается, когда мне становится 3?
Да.
Если это закончится, элемент не должен оставаться 'item2'?
Нет. Этот пример немного сложен. Во время последней итерации цикла i
равно 2, но он ссылается на 3-й элемент массива list
, который равен 3. Другими словами, item == ' item '+ list [2] ==' item3 '
Или переменная item создается снова, когда testList вызывает функции?
Нет, в первый раз вы были почти правы. Я думаю, вы только что пропустили тот элемент [2]
, который имеет значение 3.
Цикл заканчивается, когда i становится 3, но для переменной "item", хранящейся в замыкании и отображаемой предупреждением, устанавливается значение
var item = 'item' + list[i];
текст "item" + значение в списке [2]. Третий элемент списка - 3, поэтому текст - item3
Я думаю, что вам не хватает того, что list [i]
недооценено, потому что i
равно 3, а list
определен только для 0 .. 2.
Переменная list
хранится в закрытии, как вы говорите.
На самом деле вы можете получить доступ к переменной list
, но вы пытаетесь получить доступ к list [3]
. В конце концов, переменная i
также сохраняется как закрытие, и ее значение равно 3, когда вызывается функция console.log
.
Цикл for в buildList завершается до того, как вы сделаете следующее:
for (var j = 0; j < fnlist.length; j++) {
fnlist[j]();
}
... следовательно, к тому времени (когда вы вызываете каждую функцию) переменная item
будет тем, что было присвоено ему последним (т.е. "item3"), а i
будет 3
(в результате последней операции i ++
), и список [3]
равен undefined
.
Это все связано с тем, что цикл завершается до того, как вы вызываете функцию closure'd . Чтобы предотвратить это, вы можете создать новое закрытие, например:
function buildList(list) {
var result = [];
for (var i = 0; i < list.length; i++) {
var item = 'item' + list[i];
result.push(
(function(item, i){
// Now we have our own "local" copies of `item` and `i`
return function() {
console.log(item + ' ' + list[i])
};
})(item, i)
);
}
return result;
}