我正在尝试使用LINQ.假设我有两个相同长度的集合:
var first = new string[] { "1", "2", "3" };
var second = new string[] { "a", "b", "c" };
Run Code Online (Sandbox Code Playgroud)
我想将这两个集合合并为一个,但是以交错的方式.因此,结果序列应为:
"1", "a", "2", "b", "3", "c"
Run Code Online (Sandbox Code Playgroud)
到目前为止,我想出的是一个Zip匿名类型和SelectMany:
var result = first.Zip( second, ( f, s ) => new { F = f, S = s } )
.SelectMany( fs => new string[] { fs.F, fs.S } );
Run Code Online (Sandbox Code Playgroud)
有没有人知道用LINQ实现这种交错合并的替代/简单方法?
Dou*_*las 29
警告:如果枚举具有不同的长度,这将跳过尾随元素.如果您宁愿用空值替换填充较短的集合,请使用Andrew Shepherd的答案.
您可以编写自己的Interleave扩展方法,就像在此示例中一样.
internal static IEnumerable<T> InterleaveEnumerationsOfEqualLength<T>(
this IEnumerable<T> first,
IEnumerable<T> second)
{
using (IEnumerator<T>
enumerator1 = first.GetEnumerator(),
enumerator2 = second.GetEnumerator())
{
while (enumerator1.MoveNext() && enumerator2.MoveNext())
{
yield return enumerator1.Current;
yield return enumerator2.Current;
}
}
}
Run Code Online (Sandbox Code Playgroud)
And*_*erd 28
通过免除匿名类型,您提供的示例可以更简单:
var result = first.Zip(second, (f, s) => new[] { f, s })
.SelectMany(f => f);
Run Code Online (Sandbox Code Playgroud)
接受的答案中给定的实现具有不一致性:
结果序列将始终包含第一个序列的所有元素(因为外部while循环),但如果第二个序列包含更多元素,则不会附加这些元素.
从一种Interleave方法我可以期望得到的序列包含
min(length_1, length_2) * 2),或者那个length_1 + length_2.以下实现遵循第二种方法.
注意|或者比较中的单个,这避免了短路评估.
public static IEnumerable<T> Interleave<T> (
this IEnumerable<T> first, IEnumerable<T> second)
{
using (var enumerator1 = first.GetEnumerator())
using (var enumerator2 = second.GetEnumerator())
{
bool firstHasMore;
bool secondHasMore;
while ((firstHasMore = enumerator1.MoveNext())
| (secondHasMore = enumerator2.MoveNext()))
{
if (firstHasMore)
yield return enumerator1.Current;
if (secondHasMore)
yield return enumerator2.Current;
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以根据索引循环并选择数组:
var result =
Enumerable.Range(0, first.Length * 2)
.Select(i => (i % 2 == 0 ? first : second)[i / 2]);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5267 次 |
| 最近记录: |