Reputation: 10513
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?
Upvotes: 1
Views: 655
Reputation: 38106
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
};
Upvotes: 1
Reputation: 113402
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.
Upvotes: 2
Reputation: 4431
By using union() of Linq you can join 2 same element ordered collections...
Upvotes: 0