X元素的集合,想要以两个为一组遍历它们(使用Linq?)

时间:2010-10-11 12:38:53

标签: c# linq

我有8个元素的集合。我想以这样的方式遍历它,经过2次迭代后我会做其他事情,然后再回到遍历。

实际应用是制作布局。我放了两个方框,然后我打印了一个新的线,然后我放了两个方框。

有没有办法可以使用Linq将序列集合变成这样的东西?也许使用Group by子句?但是想不出解决方案。

收藏 - > “1,2,3,4,5,6,7,8”

想要打印

1 2

3 4

5 6

7 8

5 个答案:

答案 0 :(得分:2)

使用扩展方法,如下所示:

public static IEnumerable<Tuple<TElement, TElement>> AsPairs<TElement>(this IEnumerable<TElement> @this)
{
    IEnumerator<TElement> enumerator = @this.GetEnumerator();

    while (enumerator.MoveNext())
    {
        TElement left = enumerator.Current;

        if (enumerator.MoveNext())
        {
            TElement right = enumerator.Current;

            yield return Tuple.Create(left, right);
        }
        else
        {
            throw new ArgumentException("this", "Expected an even number of elements.");
        }
    }
}

...
foreach (Tuple<TextBox, TextBox> pair = textBoxes.AsPairs())
{
    ...
}

编辑:在不确定的可枚举案例中添加了例外。

答案 1 :(得分:0)

没有内置的LINQ方法可以用来做到这一点 您可以滥用Aggregate来执行此操作,但我不会推荐它。

如果你愿意,你可以自己写。

例如:

<击>

<击>
public static IEnumerable<IEnumerable<T>> Subdivide<T>(this IEnumerable<T> source, int groupsize) {
    using(var e = source.GetEnumerator()) {
        while(true) {
            bool isFinished = false;
            var g = Subgroup(e, groupsize, b => isFinished = b);
            if (isFinished)
                yield break;
            else
                yield return g;
        }
    }
}

static IEnumerable<T> Subgroup<T>(IEnumerator<T> e, int size, Action<bool> finishedSetter) {
    finishedSetter(true);
    int c = 0;
    while(e.MoveNext() && ++c <= size) {
        finishedSetter(false);
        yield return e.Current;
    }
}            

编辑:根据定义,这不起作用。 由于懒惰的评估,不能依赖嵌套的迭代器 相反,您可以使用以下方法:

public static IEnumerable<IEnumerable<T>> Subdivide<T>(this IEnumerable<T> source, int groupSize) {
    var currentGroup = new List<T>(groupSize);
    foreach(var item in source) {
        currentGroup.Add(item);
        if (currentGroup.Count == groupSize) {
            yield return currentGroup;
            currentGroup = new List<T>(groupSize);
        }
    }
    if (currentGroup.Count != 0) 
        yield return currentGroup;
}

答案 2 :(得分:0)

你可以做一些使用skip和

的事情
collection.Take(2) - takes first 2 elements
collection.Skip(2).Take(2) - skips first 2 and takes elements 3 and 4 

我不确定您的代码,但我相信如果您可以使用它可能会有所帮助

答案 3 :(得分:0)

这是您的解决方案

    private static void TraverseInTwos()
    {
        var col = new Collection<int> { 1, 2, 3, 4, 5, 6, 7, 8 };
        int i = 0;
        while (col.Skip(i).Any())
        {
            var newCol = col.Skip(i).Take(2);
            Console.WriteLine(newCol.First() + " " + ((newCol.Count() > 1) ? newCol.Last().ToString() : string.Empty));
            i += 2;
        }
    }

答案 4 :(得分:0)

你走了:))

var ten = Enumerable.Range(20, 10);
var pairs = ten.Select((i,index) => new { group = (index >> 1), val = i }).GroupBy(a => a.group);

foreach (var pair in pairs)
{
    foreach (var i in pair) Console.Write(i.val + " ");
    Console.WriteLine();
}

/莫伯格