使用 LINQ 连接两个有序集合

发布于 2024-12-17 18:32:55 字数 831 浏览 0 评论 0原文

我有两种数据类型,FooBar,它们有一个属性来确定顺序:

class Foo
{
    public int Order { get; set; }
    public string FooValue { get; set; }
}

class Bar
{
    public int Order { get; set; }
    public string BarValue { get; set; }
}

然后我有这些类型的两个集合。我想加入集合,以便结果将包含 FooBar 对。对的数量应该是 Bar 元素的数量。

每对应包含一个 Bar 元素和最近的 Foo 元素(具有最大的 Foo Order 值,以当前 Bar <代码>订单值)。

例如,对于以下集合(省略了一些语句):

var foos = new [] { (1, "Foo1"), (2, "Foo2"), (5, "Foo5"), (7, "Foo7") };
var bars = new [] { (1, "Bar1"), (6, "Bar6") };

结果将是:

result = { 
    ((1, "Bar1"), (1, "Foo1")),
    ((6, "Bar6"), (5, "Foo5"))
};

如何使用 LINQ 和 C# 4.0 实现此目的?

I've got two data types, Foo and Bar, that have a property to determine order:

class Foo
{
    public int Order { get; set; }
    public string FooValue { get; set; }
}

class Bar
{
    public int Order { get; set; }
    public string BarValue { get; set; }
}

Then I've got two collections of these types. I'd like to join the collections, so that the result will be contain pairs of Foo and Bar. The number of pairs should be the number of Bar elements.

Each pair should consist of a Bar element and the most "recent" Foo element (with largest Foo Order value, bounded by the current Bar Order value).

For example, for the following collections (some statements omitted):

var foos = new [] { (1, "Foo1"), (2, "Foo2"), (5, "Foo5"), (7, "Foo7") };
var bars = new [] { (1, "Bar1"), (6, "Bar6") };

The result would be:

result = { 
    ((1, "Bar1"), (1, "Foo1")),
    ((6, "Bar6"), (5, "Foo5"))
};

How can I achieve this with LINQ and C# 4.0?

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

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

发布评论

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

评论(3

节枝 2024-12-24 18:32:55

假设 foosOrder 排序,您可以这样做:

var fubars = from bar in bars
             let bestFoo = foos.TakeWhile(foo => foo.Order <= bar.Order)
                               .LastOrDefault()
             select new { Bar = bar, Foo = bestFoo };

否则,我建议先对 foos 进行排序。

您可以通过使用二分搜索(例如使用Array.BinarySearch)而不是像我的示例中那样使用线性搜索来提高此查询的效率。

Assuming foos are sorted by Order, you can do:

var fubars = from bar in bars
             let bestFoo = foos.TakeWhile(foo => foo.Order <= bar.Order)
                               .LastOrDefault()
             select new { Bar = bar, Foo = bestFoo };

Otherwise, I suggest sorting the foos first.

You can make this query much more efficient by using binary search (e.g. wih Array.BinarySearch) instead of linear search as in my sample.

笑脸一如从前 2024-12-24 18:32:55

如果在多个 bar 对象的绑定 foo 相同的情况下允许 foo 重复:

var result = bars.Zip(foos, 
        (b,f) => Tuple.Create(b, foos.TakeWhile(foo => foo.Order <= b.Order).Last()));

当然,它仍然比迭代效率低,因为TakeWhile 将为每个 bars 对象调用(每次从头开始)

我所说的 foo 重复是指对于诸如

var foos = new [] { new Foo(1, "Foo1"), new Foo(3, "Foo3"), new Foo(5, "Foo5")};
var bars = new [] { new Bar(1, "Bar1"), new Bar(2, "Bar2") };

结果将是

{ 
    ((1, "Bar1"), (1, "Foo1")),
    ((2, "Bar2"), (1, "Foo1")) //Foo1 again
};

If you allow foo repetitions in cases where the bound foo is the same for several bar objects:

var result = bars.Zip(foos, 
        (b,f) => Tuple.Create(b, foos.TakeWhile(foo => foo.Order <= b.Order).Last()));

Of course it's still less efficient than iterating, since TakeWhile will be called for each bars object (starting from the beginning each time)

What I mean by foo repetitions is that for an input such as

var foos = new [] { new Foo(1, "Foo1"), new Foo(3, "Foo3"), new Foo(5, "Foo5")};
var bars = new [] { new Bar(1, "Bar1"), new Bar(2, "Bar2") };

The result would be

{ 
    ((1, "Bar1"), (1, "Foo1")),
    ((2, "Bar2"), (1, "Foo1")) //Foo1 again
};
不如归去 2024-12-24 18:32:55

通过使用 Linq 的 union() ,您可以连接 2 个相同元素的有序集合...

By using union() of Linq you can join 2 same element ordered collections...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文