"解压缩"在C#或最好的选择了IEnumerable动态 [英] "Unzip" IEnumerable dynamically in C# or best alternative

查看:134
本文介绍了"解压缩"在C#或最好的选择了IEnumerable动态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我们假设你有一个函数返回一个懒洋洋地枚举对象:

Lets assume you have a function that returns a lazily-enumerated object:

struct AnimalCount
{
    int Chickens;
    int Goats;
}

IEnumerable<AnimalCount> FarmsInEachPen()
{
    ....
    yield new AnimalCount(x, y);
    ....
}

您还可以消耗两个功能两个不同的的IEnumerable S,例如:

You also have two functions that consume two separate IEnumerables, for example:

ConsumeChicken(IEnumerable<int>);
ConsumeGoat(IEnumerable<int>);

你怎么能叫 ConsumeChicken ConsumeGoat 无)转换 FarmsInEachPen()了ToList()事前,因为它可能有两个数不胜数的记录,B)没有多线程。

How can you call ConsumeChicken and ConsumeGoat without a) converting FarmsInEachPen() ToList() beforehand because it might have two zillion records, b) no multi-threading.

基本上是:

ConsumeChicken(FarmsInEachPen().Select(x => x.Chickens));
ConsumeGoats(FarmsInEachPen().Select(x => x.Goats));

但不强制双重枚举。

But without forcing the double enumeration.

我可以多线程解决它,但它被不必要地复杂化了缓冲队列为每个列表。

I can solve it with multithread, but it gets unnecessarily complicated with a buffer queue for each list.

所以我在寻找一种方式来 AnimalCount 枚举分成两个 INT 调查员没有充分评估 AnimalCount 。目前运行没有问题 ConsumeGoat ConsumeChicken 一起在锁步。

So I'm looking for a way to split the AnimalCount enumerator into two int enumerators without fully evaluating AnimalCount. There is no problem running ConsumeGoat and ConsumeChicken together in lock-step.

我能感觉到解刚走出我的把握,但我不能令人信服。我沿着一个辅助函数返回一个的IEnumerable行思被送入 ConsumeChicken 每一次的迭代器时,它在内部调用 ConsumeGoat ,因此在执行锁步的两个功能。除,当然,我也不想叫 ConsumeGoat 不止一次。

I can feel the solution just out of my grasp but I'm not quite there. I'm thinking along the lines of a helper function that returns an IEnumerable being fed into ConsumeChicken and each time the iterator is used, it internally calls ConsumeGoat, thus executing the two functions in lock-step. Except, of course, I don't want to call ConsumeGoat more than once..

推荐答案

我想通了,由于道路在很大程度上归功于该@Lee把我的。

I figured it out, thanks in large part due to the path that @Lee put me on.

您需要两个拉链之间共享一个枚举器,并使用适配器函数来预测正确的元素插入的顺序。

You need to share a single enumerator between the two zips, and use an adapter function to project the correct element into the sequence.

private static IEnumerable<object> ConsumeChickens(IEnumerable<int> xList)
{
    foreach (var x in xList)
    {
        Console.WriteLine("X: " + x);
        yield return null;
    }
}

private static IEnumerable<object> ConsumeGoats(IEnumerable<int> yList)
{
    foreach (var y in yList)
    {
        Console.WriteLine("Y: " + y);
        yield return null;
    }
}

private static IEnumerable<int> SelectHelper(IEnumerator<AnimalCount> enumerator, int i)
{
    bool c = i != 0 || enumerator.MoveNext();
    while (c)
    {
        if (i == 0)
        {
            yield return enumerator.Current.Chickens;
            c = enumerator.MoveNext();
        }
        else
        {
            yield return enumerator.Current.Goats;
        }
    }
}

private static void Main(string[] args)
{
    var enumerator = GetAnimals().GetEnumerator();

    var chickensList = ConsumeChickens(SelectHelper(enumerator, 0));
    var goatsList = ConsumeGoats(SelectHelper(enumerator, 1));

    var temp = chickensList.Zip(goatsList, (i, i1) => (object) null);
    temp.ToList();

    Console.WriteLine("Total iterations: " + iterations);
}

这篇关于&QUOT;解压缩&QUOT;在C#或最好的选择了IEnumerable动态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆