猿问

将两个序列与其元素交错连接

我想连接两个序列的元素,生成一个包含原始两个序列的所有元素的单个序列,但它们的元素交错。

ConcatLINQ 方法可以进行连接但没有交错,所以我需要一些特别的东西。

交错规则如下:

  • 对于每对元素,selector应该调用一个函数,并且选择的元素应该是第一个或第二个,具体取决于boolean函数的结果(true:第一个,false:第二个)

这是我想要实现的实际示例:

var sequence1 = new int[] { 1, 2, 3 };

var sequence2 = new int[] { 11, 12, 13 };

var result = sequence1.ConcatInterleaved(sequence2, (a, b) => (a + b) % 3 == 0);

Console.WriteLine(String.Join("\r\n", result));

预期输出:


1  // Because (1 + 11) % 3 == 0, the first is selected

11 // Because (2 + 11) % 3 != 0, the second is selected

12 // Because (2 + 12) % 3 != 0, the second is selected

2  // Because (2 + 13) % 3 == 0, the first is selected

13 // Because (3 + 13) % 3 != 0, the second is selected

3  // Because sequence2 has no more elements, the next element of sequence1 is selected

我想要一个 LINQ 解决方案,以便本着内置 LINQ 方法的精神可以推迟实际的串联。这是我目前的尝试:


public static IEnumerable<TSource> ConcatInterleaved<TSource>(

    this IEnumerable<TSource> source,

    IEnumerable<TSource> other,

    Func<TSource, TSource, bool> selector)

{

    // What to do?

}

更新:我更改了示例,因此它看起来不像是简单的交替交错。


关于该selector函数的说明:该函数不适用于两个序列的预选对,就像它在Zip方法中发生的那样。这些对不是预定义的。每次选择后都会形成一个新对,其中包含先前选择的拒绝元素和先前选择的序列中的新元素。


例如对于选择器(a, b) => truetheConcatInterleaved变得等效于Concat:返回 sequence1 的所有元素,然后是 sequence2 的所有元素。另一个例子:使用选择器(a, b) => false返回 sequence2 的所有元素,然后是 sequence1 的所有元素。


蝴蝶不菲
浏览 114回答 1
1回答

烙印99

public static IEnumerable<T> Weave(&nbsp; this IEnumerable<T> left,&nbsp; IEnumerable<T> right,&nbsp; Func<T, T, bool> chooser){&nbsp; using(var leftEnum = left.GetEnumerator())&nbsp; using(var rightEnum = right.GetEnumerator())&nbsp; {&nbsp; &nbsp; bool moreLeft = leftEnum.MoveNext;&nbsp; &nbsp; bool moreRight = rightEnum.MoveNext;&nbsp; &nbsp; while(moreLeft && moreRight)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; if (chooser(leftEnum.Current, rightEnum.Current))&nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; yield return leftEnum.Current;&nbsp; &nbsp; &nbsp; &nbsp; moreLeft = leftEnum.MoveNext();&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; else&nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; yield return rightEnum.Current;&nbsp; &nbsp; &nbsp; &nbsp; moreRight = rightEnum.MoveNext();&nbsp; &nbsp; &nbsp; }&nbsp;&nbsp; &nbsp; }&nbsp; &nbsp; // yield the buffered item, if any&nbsp; &nbsp; if (moreLeft) yield return leftEnum.Current;&nbsp; &nbsp; if (moreRight) yield return rightEnum.Current;&nbsp; &nbsp; // yield any leftover elements&nbsp; &nbsp; while (leftEnum.MoveNext()) yield return leftEnum.Current;&nbsp; &nbsp; while (rightEnum.MoveNext()) yield return rightEnum.Current;&nbsp; }}
随时随地看视频慕课网APP
我要回答