如何处理多个 Enumerable.Zip 调用?

Posted

技术标签:

【中文标题】如何处理多个 Enumerable.Zip 调用?【英文标题】:How to deal with multiple Enumerable.Zip calls? 【发布时间】:2019-03-13 07:25:07 【问题描述】:

我有几个带有传感器数据的枚举

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
        // ...
    );

如您所见,这是因为所有这些匿名类型都具有可读性。

有没有更好的方法来做到这一点而不会失去理智?

【问题讨论】:

***.com/questions/44378137/… 【参考方案1】:

@Michael Liu 的链接指向 Jon Skeet 的一些代码,它为您的问题提供了一个干净的解决方案,即创建一个处理 3 个序列的自定义 zip:

    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);
            
        
    

【讨论】:

【参考方案2】:

您可以在这里做的不多,但您可以提高可读性并删除一种匿名类型:

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],
    );

【讨论】:

以上是关于如何处理多个 Enumerable.Zip 调用?的主要内容,如果未能解决你的问题,请参考以下文章

如何处理单个页面上的多个异步错误?

如何处理完成闭包中的多个错误

Android/Parse-如何处理来自 ParseQuery 的多个回调

智能合约如何处理多个用户和不同的存储?

configure.ac中如何处理多个版本的Automake

Aerospike如何处理通过多个连接创建同一记录?