Как справиться с несколькими вызовами Enumerable.Zip? - PullRequest
0 голосов
/ 08 октября 2018

У меня есть несколько перечисляемых с данными от датчиков

time_elapsed, speed_x, speed_y, speed_z, высота, широта, долгота…

Каждый список имеет одинаковое количество элементов.

Я хочу объединить данные всех списков в последовательность элементов состояния.

class Status 
{
    public int TimeElapsed {get; set; }
    public double SpeedX {get; set; }
    public double SpeedY {get; set; }
    public double SpeedZ {get; set; }
   ...
}

Я думал об использовании метода Enumerable.Zip, но он выглядит действительно громоздким:

var statuses = time_elapsed
    .Zip(speed_x, (a, b) => new { a,  b})
    .Zip(speed_y, (c, d) => new { c,  d})
    .Zip(speed_z, (e, f) => new { e , f})
    .Select(x => new Status
    {
        Time = x.e.c.a,
        SpeedX = x.e.c.b,
        SpeedY = x.e.d,
        SpeedZ = x.f
        // ...
    });

Как вы видите, это из-за того, что вы читаете все эти анонимные типы.

Есть ли лучший способ сделать это, не потеряв голову?

Ответы [ 2 ]

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

Ссылка от @Michael Liu указала на некоторый код от Jon Skeet, который обеспечивает чистое решение вашей проблемы, а именно создание собственного zip-файла, который обрабатывает 3 последовательности:

    static IEnumerable<TResult> Zip<TFirst, TSecond, TThird, TResult>(
    IEnumerable<TFirst> first,
    IEnumerable<TSecond> second,
    IEnumerable<TThird> third,
    Func<TFirst, TSecond, TThird, TResult> resultSelector)
    {
        using (IEnumerator<TFirst> iterator1 = first.GetEnumerator())
        using (IEnumerator<TSecond> iterator2 = second.GetEnumerator())
        using (IEnumerator<TThird> iterator3 = third.GetEnumerator())
        {
            while (iterator1.MoveNext() && iterator2.MoveNext() && iterator3.MoveNext())
            {
                yield return resultSelector(iterator1.Current, iterator2.Current, iterator3.Current);
            }
        }
    }
0 голосов
/ 08 октября 2018

Мало что вы можете сделать здесь, но вы можете улучшить читабельность и удалить один анонимный тип:

var statuses = time_elapsed
    .Zip(speed_x, (time, speedX) => new {time, speedX})
    .Zip(speed_y, (x, speedY) => new {x.time, x.speedX, speedY})
    .Zip(speed_z, (x, speedZ) => new Status
    {
        TimeElapsed = x.time,
        SpeedX = x.speedX,
        SpeedY = x.speedY,
        SpeedZ = speedZ
    });

Вы также можете использовать этот подход:

int minSize = new IList[] {time_elapsed, speed_x, speed_y, speed_z}.Min(c => c.Count);
IEnumerable<Status> statuses = Enumerable.Range(0, minSize)
    .Select(i => new Status
    {
        TimeElapsed = time_elapsed[i],
        SpeedX = speed_x[i],
        SpeedY = speed_y[i],
        SpeedZ = speed_z[i],
    });
...