Я написал метод для разбивки списка элементов на несколько списков с использованием System.Linq
. Когда я запускаю этот метод для 50000 простых целых чисел, он принимает около 59.862 секунд.с выпуском System.Linq при разбиении списка на несколько списков
Stopwatch watchresult0 = new Stopwatch();
watchresult0.Start();
var result0 = SubDivideListLinq(Enumerable.Range(0, 50000), 100).ToList();
watchresult0.Stop();
long elapsedresult0 = watchresult0.ElapsedMilliseconds;
Так что я пытался форсировать его, и написал его с простой итерации цикла по каждому пункту в моем списке, и это нужно только 4 миллисекунды:
Stopwatch watchresult1 = new Stopwatch();
watchresult1.Start();
var result1 = SubDivideList(Enumerable.Range(0, 50000), 100).ToList();
watchresult1.Stop();
long elapsedresult1 = watchresult1.ElapsedMilliseconds;
Это мой Subdivide-метод с помощью Linq:
private static IEnumerable<List<T>> SubDivideListLinq<T>(IEnumerable<T> enumerable, int count)
{
while (enumerable.Any())
{
yield return enumerable.Take(count).ToList();
enumerable = enumerable.Skip(count);
}
}
И это мой Subdivide-метод с foreach
цикла по каждому пункту:
private static IEnumerable<List<T>> SubDivideList<T>(IEnumerable<T> enumerable, int count)
{
List<T> allItems = enumerable.ToList();
List<T> items = new List<T>(count);
foreach (T item in allItems)
{
items.Add(item);
if (items.Count != count) continue;
yield return items;
items = new List<T>(count);
}
if (items.Any())
yield return items;
}
у вас есть идеи, почему моя собственная реализация намного быстрее, чем разделение на Linq? Или я делаю что-то неправильно?
И: Как вы можете видеть, я знаю, как разделять списки, так что это не дублированный связанный с этим вопрос. Я хотел знать о производительности между linq и моей реализацией. Не как разделить-списки
Версия LINQ будет выполнять запрос дважды на итерацию. Он также будет иметь пустые циклы, которые всегда должны найти последнюю позицию, тогда как ваш оптимизированный метод может продолжить обработку. Он также будет инициализировать список с правильным размером, тогда как LINQ должен каждый раз изменять размер внутреннего массива. –
также не использовать 'while (перечисляемый.Any())'. с некоторыми итераторами вы можете пропустить значения. вы должны либо безопасно получить все значения, например, используя 'foreach', либо использовать' MoveNext' и 'Current' –
, но' enumerable.Any() 'возвращает true/false, когда' перечисляемый' присваивается элементам 'Skip'ped , Зачем мне скучать по ценностям здесь? –