邮编ñ的IEnumerable< T> S在一起吗?同时迭代呢?邮编、迭代、IEnumerable、LT

2023-09-03 03:31:20 作者:▇▇▇▇刮开试试

我: -

IEnumerable<IEnumerable<T>> items;

和我想创建: -

IEnumerable<IEnumerable<T>> results;

凡在结果的第一个项目是一个IEnumerable每一个项目的IEnumerables中的第一个项目,在结果的第二项是每一个项目,等第二个项目的一个IEnumerable

where the first item in "results" is an IEnumerable of the first item of each of the IEnumerables of "items", the second item in "results" is an IEnumerable of the second item of each of "items", etc.

的IEnumerables不一定相同的长度。如果某些项目IEnumerables不具有特定索引处的元素,那么我期望匹配的IEnumerable的结果有它的项目较少。

The IEnumerables aren't necessarily the same lengths. If some of the IEnumerables in items don't have an element at a particular index, then I'd expect the matching IEnumerable in results to have fewer items in it.

例如: -

items = { "1", "2", "3", "4" } , { "a", "b", "c" };
results = { "1", "a" } , { "2", "b" }, { "3", "c" }, { "4" };

编辑:另一个例子(在意见要求): -

Another example (requested in comments):-

items = { "1", "2", "3", "4" } , { "a", "b", "c" }, { "p", "q", "r", "s", "t" };
results = { "1", "a", "p" } , { "2", "b", "q" }, { "3", "c", "r" }, { "4", "s" }, { "t" };

我不知道提前多少序列有,也没有多少元素各自的顺序进行。我可能有1000个序列,在每个百万元,我可能只需要前〜10,所以我想,如果我可以使用源序列(懒惰)枚举。我特别不希望创建一个新的数据结构,如果我能帮助它。

I don't know in advance how many sequences there are, nor how many elements are in each sequence. I might have 1,000 sequences with 1,000,000 elements in each, and I might only need the first ~10, so I'd like to use the (lazy) enumeration of the source sequences if I can. In particular I don't want to create a new data structure if I can help it.

有一个内置的方法(类似于IEnumerable.Zip),可以做到这一点?

Is there a built-in method (similar to IEnumerable.Zip) that can do this?

有另一种方式?

推荐答案

现在轻轻测试,并与处置工作。

Now lightly tested and with working disposal.

public static class Extensions
{
  public static IEnumerable<IEnumerable<T>> JaggedPivot<T>(
    this IEnumerable<IEnumerable<T>> source)
  {
    List<IEnumerator<T>> originalEnumerators = source
      .Select(x => x.GetEnumerator())
      .ToList();

    try
    {
      List<IEnumerator<T>> enumerators = originalEnumerators
        .Where(x => x.MoveNext()).ToList();

      while (enumerators.Any())
      {
        List<T> result = enumerators.Select(x => x.Current).ToList();
        yield return result;
        enumerators = enumerators.Where(x => x.MoveNext()).ToList();
      }
    }
    finally
    {
      originalEnumerators.ForEach(x => x.Dispose());
    }
  } 
}

public class TestExtensions
{
  public void Test1()
  {
    IEnumerable<IEnumerable<int>> myInts = new List<IEnumerable<int>>()
    {
      Enumerable.Range(1, 20).ToList(),
      Enumerable.Range(21, 5).ToList(),
      Enumerable.Range(26, 15).ToList()
    };

    foreach(IEnumerable<int> x in myInts.JaggedPivot().Take(10))
    {
      foreach(int i in x)
      {
        Console.Write("{0} ", i);
      }
      Console.WriteLine();
    }
  }
}