我有两种数据类型Foo
和Bar
,它们具有确定顺序的属性:
class Foo
{
public int Order { get; set; }
public string FooValue { get; set; }
}
class Bar
{
public int Order { get; set; }
public string BarValue { get; set; }
}
然后我有两个这些类型的集合。我想加入这些集合,因此结果将包含Foo
和Bar
对。对的数量应该是Bar
个元素的数量。
每对应包含Bar
元素和最“最近”的Foo
元素(具有最大的Foo Order
值,以当前条形Order
值为界)
例如,对于以下集合(省略了一些语句):
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实现这一目标?
答案 0 :(得分:2)
假设foos
按Order
排序,您可以执行以下操作:
var fubars = from bar in bars
let bestFoo = foos.TakeWhile(foo => foo.Order <= bar.Order)
.LastOrDefault()
select new { Bar = bar, Foo = bestFoo };
否则,我建议先排序foos
。
您可以使用二进制搜索(例如wih Array.BinarySearch
)而不是我的示例中的线性搜索来提高此查询的效率。
答案 1 :(得分:1)
如果在多个foo
对象的绑定foo
相同的情况下允许bar
次重复:
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
};
答案 2 :(得分:0)
通过使用Linq的union(),您可以加入2个相同的元素有序集合...