Muszę uśrednić 3 IEnumerable kolekcji i utworzyć nowy IEnumerable z następującym wynikiem:

var result1 = GetResult1()//Returns an enumerable collection having elements 1,2,3,4

var result2 = GetResult2()//Returns an enumerable collection having elements 3,4,2,6

var result3 = GetResult3()//returns an enumerable collection having elements 2,5,1,6

//I need to create a collection which has the averages of the above results as below:

var result4 = GetResult4()//Should return 2.00,3.67,2.33,5.33.
  • Każdy wynik będzie miał taką samą liczbę elementów, tj. wynik1, wynik2, wynik3 będzie miał taką samą liczbę elementów (w tym przypadku 4, ale w rzeczywistości może wynosić do 1500).

  • Każdy element wyniku odpowiada średniej wartości wyników, tj. w zbiorze wyników 4 pierwszy element będzie średnią 1,3,2, co odpowiada średniej pierwszego elementu odpowiednio w wyniku1, wyniku2, wyniku3 i stąd dalej.

  • Wynikowa kolekcja powinna mieć miejsca dziesiętne zaokrąglone do 2.

Oczywistą odpowiedzią jest iteracja każdego elementu w kolekcjach i ręczne tworzenie elementów w wynikowej kolekcji (tj. za pomocą pętli for), jednak chcę tego uniknąć, ponieważ wyniki będą miały blisko 1500 elementów w każdej kolekcji i chciałbym zrobić jakąś leniwą ocenę za pomocą LINQ.

Czy możesz mi pomóc z kilkoma wskazówkami?

Pozdrawiam, -Mike

0
Mike 20 luty 2012, 15:39

2 odpowiedzi

Najlepsza odpowiedź

Jeśli używasz .NET 4, możesz użyć Enumerable.Zip, aby uzyskać dobry efekt tutaj:

var averages = result1.Zip(result2, (x, y) => x + y)
                      .Zip(result3, (xy, z) => (xy + z) / 3.0d)
                      .ToList();

Nie spowoduje to żadnego zaokrąglenia — normalnie byłoby to bardziej odpowiednie w przypadku etapu formatowania. Zauważ, że i tak wartości mogą kończyć się tylko na 0, 0,33 lub 0,67, ponieważ dzielisz tylko przez 3. Tutaj użyłem double, ale inną opcją byłoby użycie decimal - to zależy o tym, co naprawdę oznaczają wartości.

7
Jon Skeet 20 luty 2012, 15:43

Jednym ze sposobów osiągnięcia tego jest napisanie metody, która pobiera listę list i wykonuje niezbędną pracę. Coś jak:

 private static IEnumerable<double> AverageOfLists(params IEnumerable<double>[] values)
 {
     var lists = values.Select(v => v.ToList()).ToArray();

     for(var i=0;i<lists[0].Count;i++)
     {
         var sum = 0.0;
         for(var j=0;j<lists.Length;j++)
         {
             sum+= lists[j][i];
         }
         yield return sum/lists.Length;
     }
 }

Wykorzystanie byłoby wtedy

var result4 = AverageOfLists(result1,result2,result3);

Przykład na żywo: http://rextester.com/IGOSE98291

NB: Nie uwzględniono zaokrąglania z tego samego powodu, o którym wspomniał @Jon; zaokrąglanie to etap formatowania/wyświetlania.

0
Jamiec 20 luty 2012, 15:50