Рассчитать средние значения нескольких IEnumerable с одинаковым количеством элементов - PullRequest
0 голосов
/ 17 октября 2018

Предполагая, что у нас есть несколько IEnumerable с одним и тем же количеством элементов

var multipleEnumerables = new[]
{
    new[] { 10, 20, 30 }
    new[] { 11, 21, 31 }
    new[] { 12, 22, 32 }
    new[] { 13, 23, 33 }
}

Как получить среднее значение для тех, кто использует LINQ, что даст следующий результат:

new[] { 11.5, 21.5, 31.5 }

Число перечисляемых может варьироваться (т. Е. Не может быть равно четырем).

Количество элементов в каждом перечислимом может варьироваться (т.е. не фиксировано до трех), но будет одинаковым для всех перечислимых для данного конкретного экземпляра.

Ответы [ 2 ]

0 голосов
/ 17 октября 2018

Из-за вашего интереса к архивированию более двух IEnumerable<T> с, вот метод расширения (ZipAll), который показывает, как сжать несколько IEnumerable<T> вместе.По сути, это вращает данные так, что столбцы становятся строками.

public static class ZipEx
{
    public static IEnumerable<IEnumerable<T>> ZipAll<T>(
                                   this IEnumerable<IEnumerable<T>> src)
    {
        return src
            .Aggregate(
                (IEnumerable<IEnumerable<T>>)null,
                (acc, curr) => acc == null
                    ? curr.Select(x => x.ToEnumerable())
                    : acc.Zip(curr, (a, c) => a.Append(c)));
    }
    public static IEnumerable<T> ToEnumerable<T>(this T item)
    {
        yield return item;
    }
}

Используя этот метод ZipAll, теперь легко:

var averages = multipleEnumerables.ZipAll().Select(x => x.Average()); //.ToArray()
0 голосов
/ 17 октября 2018

Обновление в ответ на редактирование

Если у вас есть IEnumerable<IEnumerable<Item>>, вы можете использовать что-то вроде этого:

IEnumerable<IEnumerable<Test>> multipleEnumerables = new[] {
    new [] { new Test {  Value = 10 }, new Test {  Value = 20 } },
    new [] { new Test {  Value = 11 }, new Test {  Value = 21 } }
};

var averages = multipleEnumerables
    .SelectMany(e => e.Select((v, i) => new { Index = i, Item = v }))
    .GroupBy(e => e.Index)
    .Select(e => e.Select(v => v.Item.Value).Average())
    .ToArray();

Если у вас есть простой IEnumerable<IEnumerable<int>>измените строку .Select на: .Select(e => e.Select(v => v.Item).Average()) (но, исходя из вашего комментария, я думаю, что это не так).

  1. Используйте .SelectMany для выравниваниясписок в объекты, содержащие элемент, и его индекс подмассива (поэтому 10 и 11 будут иметь Index 0 и т. д.).
  2. Группировать по индексу.
  3. Использовать .Select, чтобы выбрать среднее значение для каждой группы.

Попробуйте онлайн

Попробуйте онлайн с данными вопросов

Оригинальный ответ

Вы можете использовать .Zip, чтобы объединить два списка и вычислить среднее значение:

var averages = items1
                  .Zip(items2, (a, b) => (a+b)/2.0)
                  .ToArray();

Попробуйте онлайн

...