在c#中添加两个不同长度的列表

17 c# linq

List<double> a = new List<double>{1,2,3};
List<double> b = new List<double>{1,2,3,4,5};
Run Code Online (Sandbox Code Playgroud)

a + b应该给我2,4,6,4,5

显然我可以写一个循环,但有更好的方法吗?使用linq?

Mar*_*ell 23

您可以轻松地使用修改后的"zip"操作,但内置任何内容.例如:

    static void Main() {
        var a = new List<int> { 1, 2, 3 };
        var b = new List<int> { 1, 2, 3, 4, 5 };
        foreach (var c in a.Merge(b, (x, y) => x + y)) {
            Console.WriteLine(c);
        }
    }
    static IEnumerable<T> Merge<T>(this IEnumerable<T> first,
            IEnumerable<T> second, Func<T, T, T> operation) {
        using (var iter1 = first.GetEnumerator())
        using (var iter2 = second.GetEnumerator()) {
            while (iter1.MoveNext()) {
                if (iter2.MoveNext()) {
                    yield return operation(iter1.Current, iter2.Current);
                } else {
                    yield return iter1.Current;
                }
            }
            while (iter2.MoveNext()) {
                yield return iter2.Current;
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 因为它可以重复使用任意数量的序列和操作 - 而不仅仅是列表/索引器/添加.修复了垂直空间...更好? (4认同)

Joe*_*ung 14

使用.NET 4.0的Zip运算符:

var sums = b.Zip(a, (x, y) => x + y)
            .Concat(b.Skip(a.Count()));
Run Code Online (Sandbox Code Playgroud)

如果你想概括一下,检查哪个元素有更多,并将其用作上面的"b".


gab*_*abe 7

Enumerable.Range(0, new[] { a.Count, b.Count }.Max())
    .Select(n => a.ElementAtOrDefault(n) + b.ElementAtOrDefault(n));
Run Code Online (Sandbox Code Playgroud)

  • ElementAtOrDefault,用于IEnumerable,将(可能)遍历整个列表.可能更好地做更长的'a.Count> n?a [n]:0`代替. (3认同)
  • 就个人而言,我会使用 `Math.Max(a.Count, b.Count)` 而不是 `new[] { a.Count, b.Count }.Max()`。 (2认同)

Dam*_*ian 7

我不得不稍微调整马克对我使用的解决方案,以允许不同类型的列表,所以我想我会发布在柜面任何人都需要它.

public static IEnumerable<TResult> Merge<TFirst,TSecond,TResult>(this IEnumerable<TFirst> first,
            IEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> operation) {
    using (var iter1 = first.GetEnumerator()) {
        using (var iter2 = second.GetEnumerator()) {
            while (iter1.MoveNext()) {
                if (iter2.MoveNext()) {
                    yield return operation(iter1.Current, iter2.Current);
                } else {
                    yield return operation(iter1.Current, default(TSecond));
                }
            }
            while (iter2.MoveNext()) {
                yield return operation(default(TFirst),  iter2.Current);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)