How to write left outer join using MethodCallExpressions? - entity-framework

The code block below answers the question: "How do you perform a left outer join using linq extension methods?"
var qry = Foo.GroupJoin(
Bar,
foo => foo.Foo_Id,
bar => bar.Foo_Id,
(x,y) => new { Foo = x, Bars = y })
.SelectMany(
x => x.Bars.DefaultIfEmpty(),
(x,y) => new { Foo = x, Bar = y});
How do you write this GroupJoin and SelectMany as MethodCallExpressions? All of the examples that I've found are written using DynamicExpressions translating strings into lambdas (another example). I like to avoid taking a dependency on that library if possible.
Can the query above be written with Expressions and associated methods?
I know how to construct basic lambda expressions like foo => foo.Foo_Id using ParameterExpressions MemberExpressions and Expression.Lambda() , but how do you construct (x,y) => new { Foo = x, Bars = y })??? to be able to construct the necessary parameters to create both calls?
MethodCallExpression groupJoinCall =
Expression.Call(
typeof(Queryable),
"GroupJoin",
new Type[] {
typeof(Customers),
typeof(Purchases),
outerSelectorLambda.Body.Type,
resultsSelectorLambda.Body.Type
},
c.Expression,
p.Expression,
Expression.Quote(outerSelectorLambda),
Expression.Quote(innerSelectorLambda),
Expression.Quote(resultsSelectorLambda)
);
MethodCallExpression selectManyCall =
Expression.Call(typeof(Queryable),
"SelectMany", new Type[] {
groupJoinCall.ElementType,
resultType,
resultsSelectorLambda.Body.Type
}, groupJoinCall.Expression, Expression.Quote(lambda),
Expression.Quote(resultsSelectorLambda)));
Ultimately, I need to create a repeatable process that will left join n Bars to Foo. Because we have a vertical data structure, a left-joined query is required to return what is represented as Bars, to allow the user to sort Foo. The requirement is to allow the user to sort by 10 Bars, but I don't expect them to ever use more than three. I tried writing a process that chained the code in the first block above up to 10 times, but once I got passed 5 Visual Studio 2012 start to slow and around 7 it locked up.
Therefore, I'm now trying to write a method that returns the selectManyCall and calls itself recursively as many times as is requested by the user.
Based upon the query below that works in LinqPad, the process that needs to be repeated only requires manually handling the transparent identifiers in Expression objects. The query sorts returns Foos sorted by Bars (3 Bars in this case).
A side note. This process is significantly easier doing the join in the OrderBy delegate, however, the query it produces includes the T-SQL "OUTER APPLY", which isn't supported by Oracle which is required.
I'm grateful for any ideas on how to write the projection to anonymous type or any other out-of-the-box idea that may work. Thank you.
var q = Foos
.GroupJoin (
Bars,
g => g.FooID,
sv => sv.FooID,
(g, v) =>
new
{
g = g,
v = v
}
)
.SelectMany (
s => s.v.DefaultIfEmpty (),
(s, v) =>
new
{
s = s,
v = v
}
)
.GroupJoin (
Bars,
g => g.s.g.FooID,
sv => sv.FooID,
(g, v) =>
new
{
g = g,
v = v
}
)
.SelectMany (
s => s.v.DefaultIfEmpty (),
(s, v) =>
new
{
s = s,
v = v
}
)
.GroupJoin (
Bars,
g => g.s.g.s.g.FooID,
sv => sv.FooID,
(g, v) =>
new
{
g = g,
v = v
}
)
.SelectMany (
s => s.v.DefaultIfEmpty (),
(s, v) =>
new
{
s = s,
v = v
}
)
.OrderBy (a => a.s.g.s.g.v.Text)
.ThenBy (a => a.s.g.v.Text)
.ThenByDescending (a => a.v.Date)
.Select (a => a.s.g.s.g.s.g);

If you're having trouble figuring out how to generate the expressions, you could always get an assist from the compiler. What you could do is declare an lambda expression with the types you are going to query with and write the lambda. The compiler will generate the expression for you and you can examine it to see what expressions make up the expression tree.
e.g., your expression is equivalent to this using the query syntax (or you could use the method call syntax if you prefer)
Expression<Func<IQueryable<Foo>, IQueryable<Bar>, IQueryable>> expr =
(Foo, Bar) =>
from foo in Foo
join bar in Bar on foo.Foo_Id equals bar.Foo_Id into bars
from bar in bars.DefaultIfEmpty()
select new
{
Foo = foo,
Bar = bar,
};
To answer your question, you can't really generate an expression that creates an anonymous object, the actual type isn't known at compile time. You can cheat kinda by creating a dummy object and use GetType() to get its type which you could then use to create the appropriate new expression, but that's more of a dirty hack and I wouldn't recommend doing this. Doing so, you won't be able to generate strongly typed expressions since you don't know the type of the anonymous type.
e.g.,
var dummyType = new
{
foo = default(Foo),
bars = default(IQueryable<Bar>),
}.GetType();
var fooExpr = Expression.Parameter(typeof(Foo), "foo");
var barsExpr = Expression.Parameter(typeof(IQueryable<Bar>), "bars");
var fooProp = dummyType.GetProperty("foo");
var barsProp = dummyType.GetProperty("bars");
var ctor = dummyType.GetConstructor(new Type[]
{
fooProp.PropertyType,
barsProp.PropertyType,
});
var newExpr = Expression.New(
ctor,
new Expression[] { fooExpr, barsExpr },
new MemberInfo[] { fooProp, barsProp }
);
// the expression type is unknown, just some lambda
var lambda = Expression.Lambda(newExpr, fooExpr, barsExpr);
Whenever you need to generate an expression that involves an anonymous object, the right thing to do would be to create an known type and use that in place of the anonymous type. It will have limited use yes but it's a much cleaner way to handle such a situation. Then at least you'll be able to get the type at compile time.
// use this type instead of the anonymous one
public class Dummy
{
public Foo foo { get; set; }
public IQueryable<Bar> bars { get; set; }
}
var dummyType = typeof(Dummy);
var fooExpr = Expression.Parameter(typeof(Foo), "foo");
var barsExpr = Expression.Parameter(typeof(IQueryable<Bar>), "bars");
var fooProp = dummyType.GetProperty("foo");
var barsProp = dummyType.GetProperty("bars");
var ctor = dummyType.GetConstructor(Type.EmptyTypes);
var newExpr = Expression.MemberInit(
Expression.New(ctor),
Expression.Bind(fooProp, fooExpr),
Expression.Bind(barsProp, barsExpr)
);
// lambda's type is known at compile time now
var lambda = Expression.Lambda<Func<Foo, IQueryable<Bar>, Dummy>>(
newExpr,
fooExpr,
barsExpr);
Or, instead of creating and using a dummy type, you might be able to use tuples in your expressions instead.
static Expression<Func<T1, T2, Tuple<T1, T2>>> GetExpression<T1, T2>()
{
var type1 = typeof(T1);
var type2 = typeof(T2);
var tupleType = typeof(Tuple<T1, T2>);
var arg1Expr = Expression.Parameter(type1, "arg1");
var arg2Expr = Expression.Parameter(type2, "arg2");
var arg1Prop = tupleType.GetProperty("Item1");
var arg2Prop = tupleType.GetProperty("Item2");
var ctor = tupleType.GetConstructor(new Type[]
{
arg1Prop.PropertyType,
arg2Prop.PropertyType,
});
var newExpr = Expression.New(
ctor,
new Expression[] { arg1Expr, arg2Expr },
new MemberInfo[] { arg1Prop, arg2Prop }
);
// lambda's type is known at compile time now
var lambda = Expression.Lambda<Func<T1, T2, Tuple<T1, T2>>>(
newExpr,
arg1Expr,
arg2Expr);
return lambda;
}
Then to use it:
var expr = GetExpression<Foo, IQueryable<Bar>>();

Related

Split One Row into many based on splitting string in multiple cells

Trying to split one row into many based on string in two cells. it is similar to the question
LINQ to separate column value of a row to different rows in .net
but i need to split based on Product & Cost Columns rather than product column only
SNo.
Product
Cost
1
colgate,closeup,pepsodent
50,100,150
2
rin,surf
100
into
SNo.
Product
Cost
1
colgate
50
1
closeup
100
1
pepsodent
150
2
rin
100
2
surf
100
I'm using Linq to Object with Entity Framework
Try the following. Since you have not presented any model it can be inaccurate in names.
var loaded = ctx.Products.ToList();
var query =
from p in loaded
from sp in p.Product.Split(',').Zip(p.Cost.Split(','), (p, c) => (p, c))
select new
{
Sno = p.Sno,
Product = sp.p,
Cost = sp.c
};
var splitted = query.ToList();
Using #SvyatoslavDanyliv naming, here is an answer:
var loaded = ctx.Products.ToList();
var query =
from p in loaded
from sp in p.Product.Split(',').Zip(p.Cost.Split(','), (p, c) => (p, c))
select new
{
Sno = p.Sno,
Product = sp.p,
Cost = sp.c
};
var splitted = query.ToList();
It feels a bit complicated to me. I would prefer using an extension method to create a variant of Zip that repeats the last element of a shorter sequence to match the longer sequence:
public static class EnumerableExt {
public static IEnumerable<(T1 First,T2 Second)> ZipExtend<T1,T2>(this IEnumerable<T1> s1, IEnumerable<T2> s2) {
var s1e = s1.GetEnumerator();
var s2e = s2.GetEnumerator();
T1 s1eLast = default;
T2 s2eLast = default;
bool has_s2 = false;
if (s1e.MoveNext()) {
do {
s1eLast = s1e.Current;
if (s2e.MoveNext()) {
s2eLast = s2e.Current;
has_s2 = true;
}
else if (!has_s2)
yield break;
yield return (s1eLast, s2eLast);
} while (s1e.MoveNext());
if (has_s2)
while (s2e.MoveNext())
yield return (s1eLast, s2e.Current);
}
yield break;
}
}
Then the answer is:
var query =
from p in loaded
from pr in p.Product.Split(',').ZipExtend(p.Cost.Split(','))
select new
{
Sno = p.Sno,
Product = pr.First,
Cost = pr.Second
};
var splitted = query.ToList();

How to only emit consistent calculations?

I'm using reactive programming to do a bunch of calculations. Here is a simple example that tracks two numbers and their sum:
static void Main(string[] args) {
BehaviorSubject<int> x = new BehaviorSubject<int>(1);
BehaviorSubject<int> y = new BehaviorSubject<int>(2);
var sum = Observable.CombineLatest(x, y, (num1, num2) => num1 + num2);
Observable
.CombineLatest(x, y, sum, (xx, yy, sumsum) => new { X = xx, Y = yy, Sum = sumsum })
.Subscribe(i => Console.WriteLine($"X:{i.X} Y:{i.Y} Sum:{i.Sum}"));
x.OnNext(3);
Console.ReadLine();
}
This generates the following output:
X:1 Y:2 Sum:3
X:3 Y:2 Sum:3
X:3 Y:2 Sum:5
Notice how second output result is "incorrect" because it is showing that 3+2=3. I understand why this is happening (x is updated before the sum is updated) but I want my output calculations to be atomic/consistent - no value should be emitted until all dependent calculations are complete. My first approach was this...
Observable.When(sum.And(Observable.CombineLatest(x, y)).Then((s, xy) => new { Sum = s, X = xy[0], Y = xy[1] } ));
This seems to work for my simple example. But my actual code has LOTS of calculated values and I couldn't figure out how to scale it. For example, if there was a sum and squaredSum, I don't know how to wait for each of these to emit something before taking action.
One method that should work (in-theory) is to timestamp all the values I care about, as shown below.
Observable
.CombineLatest(x.Timestamp(), y.Timestamp(), sum.Timestamp(), (xx, yy, sumsum) => new { X = xx, Y = yy, Sum = sumsum })
.Where(i=>i.Sum.Timestamp>i.X.Timestamp && i.Sum.Timestamp>i.Y.Timestamp)
// do the calculation and subscribe
This method could work for very complicated models. All I have to do is ensure that no calculated value is emitted that is older than any core data value. I find this to be a bit of a kludge. It didn't actually work in my console app. When I replaced Timestamp with a custom extension that assigned a sequential int64 it did work.
What is a simple, clean way to handle this kind of thing in general?
=======
I'm making some progress here. This waits for a sum and sumSquared to emit a value before grabbing the data values that triggered the calculation.
var all = Observable.When(sum.And(sumSquared).And(Observable.CombineLatest(x, y)).Then((s, q, data)
=> new { Sum = s, SumSquared = q, X = data[0], Y = data[1] }));
This should do what you want:
Observable.CombineLatest(x, y, sum)
.DistinctUntilChanged(list => list[2])
.Subscribe(list => Console.WriteLine("{0}+{1}={2}", list[0], list[1], list[2]));
It waits until the sum has been updated, which means that all its sources must have been updated too.
You problem isn't because x is updated before the sum is updated per se. It's really about the way that you've constructed your query.
You've effectively created two queries: Observable.CombineLatest(x, y, (num1, num2) => num1 + num2) & Observable.CombineLatest(x, y, sum, (xx, yy, sumsum) => new { X = xx, Y = yy, Sum = sumsum }). Since in each you're subscribing to x then you've create two subscriptions. Meaning that when x updates then two lots of updates occur.
You need to avoid creating two subscriptions.
If you write your code like this:
BehaviorSubject<int> x = new BehaviorSubject<int>(1);
BehaviorSubject<int> y = new BehaviorSubject<int>(2);
Observable
.CombineLatest(x, y, (num1, num2) => new
{
X = num1,
Y = num2,
Sum = num1 + num2
})
.Subscribe(i => Console.WriteLine($"X:{i.X} Y:{i.Y} Sum:{i.Sum}"));
x.OnNext(3);
...then you correctly get this output:
X:1 Y:2 Sum:3
X:3 Y:2 Sum:5
I've started to get my head around this some more. Here is a more detailed example of what I'm trying to accomplish. This is some code that validates a first and last name, and should only generate a whole name when both parts are valid. As you can see I'm trying to use a bunch of small independently defined functions, like "firstIsValid", and then compose them together to calculate something more complex.
It seems like the challenge I'm facing here is trying to correlate inputs and outputs in my functions. For example, "firstIsValid" generates an output that says some first name was valid, but doesn't tell you which one. In option 2 below, I'm able to correlate them using Zip.
This strategy won't work if a validation function does not generate one output for each input. For example, if the user is typing web addresses and we're trying to validate them on the web, maybe we'd do a Throttle and/or Switch. There might be 10 web addresses for a single "webAddressIsValid". In that situation, I think I have to include the output with the input. Maybe have an IObservable> where the string is the web address and the bool is whether it is valid or not.
static void Main(string[] args) {
var first = new BehaviorSubject<string>(null);
var last = new BehaviorSubject<string>(null);
var firstIsValid = first.Select(i => string.IsNullOrEmpty(i) || i.Length < 3 ? false : true);
var lastIsValid = last.Select(i => string.IsNullOrEmpty(i) || i.Length < 3 ? false : true);
// OPTION 1 : Does not work
// Output: bob smith, bob, bob roberts, roberts
// firstIsValid and lastIsValid are not in sync with first and last
//var whole = Observable
// .CombineLatest(first, firstIsValid, last, lastIsValid, (f, fv, l, lv) => new {
// First = f,
// Last = l,
// FirstIsValid = fv,
// LastIsValid = lv
// })
// .Where(i => i.FirstIsValid && i.LastIsValid)
// .Select(i => $"{i.First} {i.Last}");
// OPTION 2 : Works as long as every change in a core data value generates one calculated value
// Output: bob smith, bob robert
var firstValidity = Observable.Zip(first, firstIsValid, (f, fv) => new { Name = f, IsValid = fv });
var lastValidity = Observable.Zip(last, lastIsValid, (l, lv) => new { Name = l, IsValid = lv });
var whole =
Observable.CombineLatest(firstValidity, lastValidity, (f, l) => new { First = f, Last = l })
.Where(i => i.First.IsValid && i.Last.IsValid)
.Select(i => $"{i.First.Name} {i.Last.Name}");
whole.Subscribe(i => Console.WriteLine(i));
first.OnNext("bob");
last.OnNext("smith");
last.OnNext(null);
last.OnNext("roberts");
first.OnNext(null);
Console.ReadLine();
}
Another approach here. Each value gets a version number (like a timestamp). Any time a calculated value is older than the data (or other calculated values it relies upon) we can ignore it.
public class VersionedValue {
static long _version;
public VersionedValue() { Version = Interlocked.Increment(ref _version); }
public long Version { get; }
}
public class VersionedValue<T> : VersionedValue {
public VersionedValue(T value) { Value = value; }
public T Value { get; }
public override string ToString() => $"{Value} {Version}";
}
public static class ExtensionMethods {
public static IObservable<VersionedValue<T>> Versioned<T>(this IObservable<T> values) => values.Select(i => new VersionedValue<T>(i));
public static VersionedValue<T> AsVersionedValue<T>(this T obj) => new VersionedValue<T>(obj);
}
static void Main(string[] args) {
// same as before
//
var whole = Observable
.CombineLatest(first.Versioned(), firstIsValid.Versioned(), last.Versioned(), lastIsValid.Versioned(), (f, fv, l, lv) => new {
First = f,
Last = l,
FirstIsValid = fv,
LastIsValid = lv
})
.Where(i => i.FirstIsValid.Version > i.First.Version && i.LastIsValid.Version > i.Last.Version)
.Where(i => i.FirstIsValid.Value && i.LastIsValid.Value)
.Select(i => $"{i.First.Value} {i.Last.Value}");

How can I reduce the redundancies of the fields handling of feed handler

I am subscript to a message feed for a number of fields, I need to set the values from the feed to the domain object and have code like below:
if (map.contains(quoteBidPriceAcronym)) {
quote.bid.price = Some(map.get(quoteBidPriceAcronym).get.asInstanceOf[Number].doubleValue());
quote.changed = true;
}
if (map.contains(quoteBidSizeAcronym)) {
quote.bid.size = Some(sizeMultipler() * map.get(quoteBidSizeAcronym).get.asInstanceOf[Number].intValue());
quote.changed = true;
}
if (map.contains(quoteBidNumAcronym)) {
quote.bid.num = Some(map.get(quoteBidNumAcronym).get.asInstanceOf[Number].shortValue());
quote.changed = true;
}
if (map.contains(quoteAskPriceAcronym)) {
quote.ask.price = Some(map.get(quoteAskPriceAcronym).get.asInstanceOf[Number].doubleValue());
quote.changed = true;
}
if (map.contains(quoteAskSizeAcronym)) {
quote.ask.size = Some(sizeMultipler() * map.get(quoteAskSizeAcronym).get.asInstanceOf[Number].intValue());
quote.changed = true;
}
if (map.contains(quoteAskNumAcronym)) {
quote.ask.num = Some(map.get(quoteAskNumAcronym).get.asInstanceOf[Number].shortValue());
quote.changed = true;
}
if (map.contains(quoteExchTimeAcronym)) {
quote.exchtime = getExchTime(String.valueOf(map.get(quoteExchTimeAcronym).get));
}
It look pretty redundant, any suggestion to improve it?
You can do something like:
map.get(quoteBidPriceAcronym).map { item =>
quote.bid.price = item.map(_.asInstanceOf[Number].doubleValue())
quote.changed = true
}
Other issues might be better to fix outside. E.g. why map[quoteBidPriceAcronym] is storing an Option, if your code assumes it's not going to be None?
Something like this perhaps?
val handlers = Map[String, Number => Unit] (
quoteBidPriceAcronym -> { n => quote.bid.price = Some(n.doubleValue) },
quoteBidSizeAcronym -> { n => quote.bid.size = Some(sizeMultipler() * n.intValue },
etc. ...
)
for {
(k,handler) <- handlers
values <- map.get(k).toSeq
quote.chanded = true
_ = handler(n.asInstanceof[Number])
}
Personally, I don't like code changing an object state (quote) but this is a question on Scala, not functional programming.
That said I would reverse the way you are using you map map keys. Instead of checking whether a value exists to perform some action, I'd have a map from your keys to actions and I'd iterate over your map elements.
e.g (assuming map is of the type Map[String, Any]):
val actions: Map[String, PartialFunction[Any, Unit]] = Map(
(quoteBidPriceAcronym, {case n: Number => quote.bid.price = Some(n.doubleValue())}),
(quoteBidSizeAcronym, {case n: Number => quote.bid.size = Some(sizeMultipler() * n.doubleValue())}),
...
...
)
for((k,v) <- map; action <- actions.get(k); _ <- action.lift(v))
quote.changed = true;
The for construct here iterates over map key-values, then (next level of iteration, over the possible action available for the key. If an action is found, which is a partial function, it gets lifted to make it a function from Any to Option[Unit]. That way, you can iterate in an additional inner level so quote.changed = true is only run when the action is defined for v.

Neater way to switch between two IObservables based on a third

I have two value streams and one selector stream and I'd like to produce a result stream that alternates between the value streams based on the selector. The code below gives the right result, but I don't like it.
Does anyone have anything neater?
var valueStreamA = new BehaviorSubject<int>(0);
var valueStreamB = new BehaviorSubject<int>(100);
var selectorStream = new BehaviorSubject<bool>(true);
var filteredA = valueStreamA .CombineLatest(selectorStream, (a, c) => new { A = a, C = c })
.Where(ac => ac.C)
.Select(ac => ac.A);
var filteredB = valueStreamB.CombineLatest(selectorStream, (b, c) => new { B = b, C = c })
.Where(bc => !bc.C)
.Select(bc => bc.B);
var result = Observable.Merge(filteredA, filteredB);
result.Subscribe(Console.WriteLine);
valueStreamA.OnNext(1);
valueStreamB.OnNext(101);
selectorStream.OnNext(false);
valueStreamA.OnNext(2);
valueStreamB.OnNext(102);
selectorStream.OnNext(true);
This productes the following output:
0
1
101
102
2
I'd do something like this:
var a = new BehaviorSubject<int>(0);
var b = new BehaviorSubject<int>(100);
var c = new BehaviorSubject<bool>(true);
var valueStreamA = a as IObservable<int>;
var valueStreamB = b as IObservable<int>;
var selector = c as IObservable<bool>;
var result = selector
// for every change in the selector...
.DistinctUntilChanged()
// select one of the two value streams
.Select(change => change ? valueStreamA : valueStreamB)
// and flatten the resulting wrapped observable
.Switch();
result.Subscribe(Console.WriteLine);
a.OnNext(1);
b.OnNext(101);
c.OnNext(false);
a.OnNext(2);
b.OnNext(102);
c.OnNext(true);
Could do something like:
var xs = Observable.Interval(TimeSpan.FromSeconds(1)).Select(_ => Feeds.Xs);
var ys = Observable.Interval(TimeSpan.FromSeconds(1)).Select(_ => Feeds.Ys);
var selectorSubject = new Subject<Feeds>();
var query = from selector in selectorSubject
select from merged in xs.Merge(ys)
where merged == selector
select merged;
query.Switch().Subscribe(Console.WriteLine);
OnNext into your 'selectorSubject' to change it.
There are a few differences to your example, but easy to get around:
Your question involved a selector of type bool, whereas I have been lazy and reused the Feeds enum in order to allow me to do an easy equality check (where merged == selector).
You of course could simply do (where selector ? merged == Xs : merged == Ys), or something like that to evaluate each merged item and discard ones you don't care about (depending on your selector).
Specifically, you would probably want to select not just the integer, but an identifier of the feed. Consider using something like Tuple.Create(), so you get that info with each update:
{A - 1}, {B - 101} etc. Your where can then do:
where selector ? merged.Item1 == A : merged.Item1 == B //this maps 'true' to feed A
I also used a Switch, which will cause my sample streams to restart because they are not published.
You probably want to publish yours and Connect them (make them 'hot'), so a Switch like mine doesn't cause any new side effects in the subscription. You have a subject (which is hot), but the 'behaviour' part will replace the value you passed into the constructor. Publishing and connecting would prevent that.
Shout if you are still confused. This isn't a full answer, but might give you enough to think about.
Howard.
Now much closer to your original question:
void Main()
{
var valueStreamA = new BehaviorSubject<int>(0);
var valueStreamB = new BehaviorSubject<int>(100);
var selectorStreamA = valueStreamA.Select(id => Tuple.Create("A", id)).Publish();
var selectorStreamB = valueStreamB.Select(id => Tuple.Create("B", id)).Publish();
var selectorStream = new BehaviorSubject<bool>(true);
var query = from selector in selectorStream
select from merged in selectorStreamA.Merge(selectorStreamB)
where selector == true ? merged.Item1 == "A" : merged.Item1 == "B"
select merged.Item2;
query.Switch().Subscribe(Console.WriteLine);
selectorStreamA.Connect();
selectorStreamB.Connect();
//First we get 0 output (because we are already using stream A, and it has a first value)
valueStreamA.OnNext(1); //This is output, because our selector remains as 'A'
valueStreamB.OnNext(101); //This is ignored - because we don't take from B
selectorStream.OnNext(false); //Switch to B
valueStreamA.OnNext(2); //Ignored - we are now using B only
valueStreamB.OnNext(102); //This is output
selectorStream.OnNext(true); //Switch back to A.
}
Outputs:
0
1
102

Getting the previous element of a IOrderedEnumeration

I have a enumeration of objects :
public IOrderedEnumerable<RentContract> Contracts {
get { return RentContracts.OrderByDescending(rc => rc.DateCreated); }
}
I have to compare a given RentContract instance with its previous RenContract instance on the list to highlight changes between the two objects, which is the most correct method to get the previous element ?
This is not possible directly. You can do it like this:
var input = new SomeClass[10]; //test data
var zipped = input.Zip(new SomeClass[1].Concat(input), (a, b) => { a, b });
var result = zipped.Where(x => x.b == null || x.a.DateCreated < x.b.DateCreated.AddHours(-1)); //some example
This solution is zipping the sequence with itself, but offset by one null element.