如何在 C# 中最优雅地迭代并行集合?

发布于 2024-08-12 15:55:51 字数 183 浏览 4 评论 0原文

        var a = new Collection<string> {"a", "b", "c"};
        var b = new Collection<int> { 1, 2, 3 };

迭代产生一组结果“a1”、“b2”、“c3”的最优雅的方法是什么?

        var a = new Collection<string> {"a", "b", "c"};
        var b = new Collection<int> { 1, 2, 3 };

What is the most elegant way to iterate through both yielding a set of results "a1", "b2", "c3"?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

淡墨 2024-08-19 15:55:51

这称为“压缩”或“压缩连接”两个序列。 Eric Lippert 描述了这个算法并提供了一个实现。

This is known as "zipping" or "zip joining" two sequences. Eric Lippert describes this very algorithm and provides an implementation.

像你 2024-08-19 15:55:51

强大的 Bart de Smet 在这里谈论 zip 函数:

http://community.bartdesmet.net/blogs/bart/archive/2008/11/03/c-4-0 -feature-focus-part-3-intermezzo-linq-s-new-zip-operator.aspx

他最优雅的解决方案利用了 select 的重载,该重载采用 2 参数 Func 委托作为其参数。

a.Select((t,i)=>new{t,i});

在此示例中,i 仅表示正在处理的项目的索引。因此,您可以为这些匿名对象创建 2 个新的可枚举对象,并将它们加入到 i 上。

就性能而言,我会选择更明显的屈服循环。

The mighty Bart de Smet talks about zip functions here:

http://community.bartdesmet.net/blogs/bart/archive/2008/11/03/c-4-0-feature-focus-part-3-intermezzo-linq-s-new-zip-operator.aspx

His most elegant solution takes advantage of an overload of select that takes a 2 parameter Func delegate as its parameter.

a.Select((t,i)=>new{t,i});

In this example, i simply represents the index of the item being processed. So you can create 2 new enumerables of these anonymous objects and join them on i.

Performance-wise, I'd go with a more obvious yielding loop.

与君绝 2024-08-19 15:55:51

为了补充 Eric 和 Bart 的精彩帖子,下面是使用 System.Linq 3.5 运算符的实现:

public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult> (
    this IEnumerable<TFirst> first,
    IEnumerable<TSecond> second,
    Func<TFirst, TSecond, TResult> resultSelector)
{
    return from aa in a.Select((x, i) => new { x, i })
           join bb in b.Select((y, j) => new { y, j })
             on aa.i equals bb.j
           select resultSelector(aa.x, bb.y);
}

To supplement the great posts by Eric and Bart, here's an implementation using System.Linq 3.5 operators:

public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult> (
    this IEnumerable<TFirst> first,
    IEnumerable<TSecond> second,
    Func<TFirst, TSecond, TResult> resultSelector)
{
    return from aa in a.Select((x, i) => new { x, i })
           join bb in b.Select((y, j) => new { y, j })
             on aa.i equals bb.j
           select resultSelector(aa.x, bb.y);
}
睡美人的小仙女 2024-08-19 15:55:51

您可以创建一个迭代器块来优雅地处理这个问题:

public static class Ext
{
    public static IEnumerable<string> ConcatEach(this IEnumerable a,
       IEnumerable b)
    {
        var aItor = a.GetEnumerator();
        var bItor = b.GetEnumerator();

        while (aItor.MoveNext() && bItor.MoveNext())
            yield return aItor.Current.ToString() + bItor.Current;
    }
}

优雅地调用它 =) 为:

var a = new Collection<string> {"a", "b", "c"};
var b = new Collection<int> {1, 2, 3};
foreach(var joined in a.ConcatEach(b))
{
    Console.WriteLine(joined);
}

You can create an iterator block to handle this elegantly:

public static class Ext
{
    public static IEnumerable<string> ConcatEach(this IEnumerable a,
       IEnumerable b)
    {
        var aItor = a.GetEnumerator();
        var bItor = b.GetEnumerator();

        while (aItor.MoveNext() && bItor.MoveNext())
            yield return aItor.Current.ToString() + bItor.Current;
    }
}

Call it elegantly =) as:

var a = new Collection<string> {"a", "b", "c"};
var b = new Collection<int> {1, 2, 3};
foreach(var joined in a.ConcatEach(b))
{
    Console.WriteLine(joined);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文