Здравствуйте, Northrop, Вы писали:
N>Есит ряд:
N>1, 2, 3, 4, ..... n
N>Надо через LINQ получить из него ряд частичных сумм:
N>1, 3, 6, 10, ... m
N>Как это сделать?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
var m = 50;
var ll = Enumerable.Range(1, 100);
Func<int, bool> ff = (i) => (i % 3 == 0 && i < m) ? true : false;
var sum = ll.Where(x => ff(x)).Sum();
Console.WriteLine(sum);
}
}
}
Re: LINQ - Как получить частичные суммы ряда?
От:
Аноним
Дата:
07.09.09 03:52
Оценка:
Здравствуйте, Northrop, Вы писали:
N>Есит ряд:
N>1, 2, 3, 4, ..... n
N>Надо через LINQ получить из него ряд частичных сумм:
N>1, 3, 6, 10, ... m
N>Как это сделать?
самый красивый вариант
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
var sum = 0;
var ss = Enumerable.Range(1, 100).Select(x => { sum += x; return sum; });
ss.ToList().ForEach(x => Console.WriteLine(x));
}
}
}
Здравствуйте, Аноним, Вы писали:
А>самый красивый вариант
Да уж...
static void Main(string[] args)
{
// исходный код, только вывод убралint size = 50000000;
var sum = 0;
DateTime Start = DateTime.Now;
var ss = Enumerable.Range(1, size).Select(x => { sum += x; return sum; });
List<int> s = ss.ToList();
DateTime End = DateTime.Now;
TimeSpan time = End - Start;
Console.WriteLine(time);
// а теперь попробуем по-простому
Start = DateTime.Now;
int[] array = new int[size];
array[0] = 0;
for (int i = 1; i < size; i++)
array[i] = array[i - 1] + i;
End = DateTime.Now;
time = End - Start;
Console.WriteLine(time);
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Да уж...
[ поскипано ]
PD>Почти 6-кратный проигрыш!
Некошерно как-то мерить DateTime'ом, да и не особо эквивалентный код
Не забывайте, что от ленивости может быть бенефит, а так же может нельзя переиспользовать массив исходных данных (массив ли там вообще на входе?), смотря какая задача там у топикстартера
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
namespace ConsoleApp
{
public static class Program
{
public static string Test(
int iterCount, params Func<string>[] tests)
{
if (tests == null)
throw new ArgumentNullException("tests");
var thread = Thread.CurrentThread;
var oldPriority = thread.Priority;
var timer = new Stopwatch();
var buf = new StringBuilder();
try
{
// прогревочный круг :Dforeach (var test in tests) test();
thread.Priority = ThreadPriority.Highest;
int n = 1;
foreach (var test in tests)
{
timer.Start();
string name = null;
for (int i=0; i < iterCount; i++) name = test();
timer.Stop();
buf.AppendFormat(
"Test #{0} {1,16}: {2} ({3} ms)\n", n++,
name, timer.Elapsed, timer.ElapsedMilliseconds);
timer.Reset();
}
}
finally { thread.Priority = oldPriority; }
return buf.ToString();
}
static void Main()
{
const int Size = 50000;
string result = Test(1000,
() => {
int sum = 0;
var ss = Enumerable.Range(1, Size)
.Select(x => { sum += x; return sum; }).ToList();
return"Linq";
},
() => {
var xx = Enumerable.Range(1, Size)
.Aggregate(new List<int> { 0 },
(l, x) => { l.Add(l[l.Count-1] + x); return l; });
return"Linq2";
},
() => {
var xx = new List<int>();
Enumerable.Range(1, Size).Aggregate(
(a, x) => { xx.Add(x); return a; });
return"Linq3";
},
() => {
int[] array = new int[Size];
for (int i = 1; i < array.Length; i++) // use length-based loop!
array[i] = array[i-1] + i;
return"Imperative";
},
() => {
int[] array = new int[Size],
scan = new int[Size];
for(int i = 0; i < array.Length; i++) array[i] = i;
int sum = 0;
for(int i = 0; i < scan.Length; i++)
{
sum += array[i];
scan[i] = sum;
}
return"Imper.(честнее)";
});
Console.WriteLine(result);
}
}
}
Test #1 Linq: 00:00:02.8320702 (2832 ms)
Test #2 Linq2: 00:00:02.2512573 (2251 ms)
Test #3 Linq3: 00:00:01.7357650 (1735 ms)
Test #4 Imperative: 00:00:00.3250726 (325 ms)
Test #5 Imper.(честнее): 00:00:00.5843982 (584 ms)
Athlon X2 3800+
p.s. Раньше ради интереса гонял тесты, linq всегда проигрывал в 2-3 раза эквивалентному eager-коду на циклах.
Не удивительно, сколько там вызовов делегатов с замыканиями, интерфейсных вызовов IEnumerable<T> и т.п...
Простите, чушь в третьем случае написал, вот так правильно:
() => {
var xx = new List<int> { 0 };
Enumerable.Range(1, Size).Aggregate(
(a, x) => { int s = a+x; xx.Add(s); return s; });
return"Linq3";
},
Результата это не меняет, у меня даже меньше вышло, хотя это скорее всего из-за погрешности:
Test #1 Linq: 00:00:02.8420874 (2842 ms)
Test #2 Linq2: 00:00:02.2010004 (2201 ms)
Test #3 Linq3: 00:00:01.7111976 (1711 ms)
Test #4 Imperative: 00:00:00.3063548 (306 ms)
Test #5 Imper.(честнее): 00:00:00.5250748 (525 ms)
Кстати, третий случай быстрее потому что там не генерится скрытый класс для замыкания, target'ом делегата становится сам List<int> xx.
То есть доступ к нему в лямбде будет не this.xx.Add(), а просто this.Add()
Здравствуйте, Пельмешко, Вы писали:
П>Кстати, третий случай быстрее потому что там не генерится скрытый класс для замыкания, target'ом делегата становится сам List<int> xx. П>То есть доступ к нему в лямбде будет не this.xx.Add(), а просто this.Add()
А если ещё capacity подсказать списку, то выходит ещё интереснее
П>Кстати, третий случай быстрее потому что там не генерится скрытый класс для замыкания, target'ом делегата становится сам List<int> xx. П>То есть доступ к нему в лямбде будет не this.xx.Add(), а просто this.Add()
а зачем List<int> юзать?
При тех значениях (десятые доли секунды) , что GetTickCount, что QueryPerfomanceCounter — один черт. Разрешение GetTickCount — 0.015 сек. Ну не в 6 раз, так в 5.95 раз
П> () => { П> int[] array = new int[Size], П> scan = new int[Size];
П> for(int i = 0; i < array.Length; i++) array[i] = i;
П> int sum = 0; П> for(int i = 0; i < scan.Length; i++) П> { П> sum += array[i]; П> scan[i] = sum; П> }
П> return "Imper.(честнее)";
Хм, а почему же честнее ? Завел ты непонятно зачем еще один массив, да еще со значениями array[i] = i. Не обижайся, но за такие массивы я школьникам втык делал. Ибо незачем такие массивы заводить. Я бы еще понял, если бы array[]= SomeHardFunction(i), тут еще можно подискутировать, вычислять ее каждый раз или предварительно просчитать и в массив. А array[i] = i — ИМХО безобразие.
А если честнее потому, что это более соответствует тому, что генерируется LinQ — то мне до этого и дела нет. Задача поставлена ясно
Вот я и сделал этот ряд частичных сумм, и пусть мне кто-то докажет обратное. И если при этом LinQ или кто-то еще должен соорудить какие-то еще массивы или иные контейнеры — меня это не касается. Я свое дело сделал и так.
П>Не удивительно, сколько там вызовов делегатов с замыканиями, интерфейсных вызовов IEnumerable<T> и т.п...
Не удивительно. Удивительно другое — несмотря на это, находятся желающие его использовать в ситуации, когда простой императивный код занимает 3 строчки и работает в 6 раз быстрее. Вот скажи на милость (или пусть топикстартер скажет) — зачем он ему в этой задаче понадобился ???
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Не удивительно. Удивительно другое — несмотря на это, находятся желающие его использовать в ситуации, когда простой императивный код занимает 3 строчки и работает в 6 раз быстрее. Вот скажи на милость (или пусть топикстартер скажет) — зачем он ему в этой задаче понадобился ???
Ну например ему может понадобится найти максимальную из четных сумм, которые меньше заданного числа...
или еще как-то скомбинировать результирующую последовательность с другими операциями.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>А если честнее потому, что это более соответствует тому, что генерируется LinQ — то мне до этого и дела нет. Задача поставлена ясно
Вы меня простите ради Бога, каюсь, в этом я ошибался конечно, почему то решил, что топикстартер привёл ряд вида 1,2,3...n в качестве примера, я именно ожидал что у него там SomeHardFunction(i), думал задача реальная, откуда-то ряд берётся... А надо было лишь получше прочитать, извините...
PD>Не удивительно. Удивительно другое — несмотря на это, находятся желающие его использовать в ситуации, когда простой императивный код занимает 3 строчки и работает в 6 раз быстрее. Вот скажи на милость (или пусть топикстартер скажет) — зачем он ему в этой задаче понадобился ???
Не знаю Чисто академический интерес, наверное, или любовь к декларативности
Разве это не прекрасно?
Здравствуйте, Пельмешко, Вы писали:
П>Не знаю :) Чисто академический интерес, наверное, или любовь к декларативности :) П>Разве это не прекрасно? :shuffle: П>