Can't listen to ItemChanged, ItemsAdded or ItemsRemoved on ReactiveList<T> - observablecollection

I have a ReactiveObject with a Property "A" of type "ReactiveList".
In my ViewModel I'd like to sum a property of "T" of every item in my list.
I got it working, while "A" not changes its value.
But all gets "out of sync", when I assign a new value to "A" (e.g. this.A = new ReactiveList();).
Does anyone have an idea how to solve this? I hope I explained my problem clear enough.

Instead of listening to A directly, listen to this:
this.WhenAnyObservable(x => x.A.ItemsChanged).Subscribe(...);
Whenever A changes, you'll resubscribe to A. Now, knowing when to reset to do a Sum, that's a bit more tricky. Here's the lazy yet more fool-proof way to do this:
Observable.Merge(
this.WhenAny(x => x.A, _ => Unit.Default),
this.WhenAnyObservable(x => x.Changed).Select(_ => Unit.Default))
.Select(_ => this.A.Sum(x => x.SomePropOnTheItem))
.DistinctUntilChanged()
.Subscribe(x => Console.WriteLine("Latest sum is {0}", x);

1 - I'd avoid assigning new Collections continuously as part of your logic, and rather use Clear(). Which should have the same impact in terms of GC.
2- If absolutely necessary, utilize a SerialDisposable and subsribe on the main object A
this.ObservableForProperty(p=> p.A).Subscribe(newAvalue=>{
someSerialDisposable.Disposable=
newAvalue.Changed.Subscribe(_=>this.Result=this.A.Sum(x=>x.T))
});
This would dispose previous deep subscriptions on A instances.

Related

Use First() and Repeat() without restarting whole stream RxJS

I am building a trading bot using RxJS. For that i have to convert ticker data from a socket connection to candles that is getting emitted every x seconds.
I created the socketObservable like this
const subscribeObservable = Observable.fromEventPattern(h => bittrex.websockets.subscribe(['USDT-BTC'], h))
const clientCallBackObservable = Observable.fromEventPattern(h => bittrex.websockets.client(h))
const socketObservable = clientCallBackObservable
.flatMap(() => subscribeObservable)
.filter(subscribtionData => subscribtionData && subscribtionData.M === 'updateExchangeState')
.flatMap(exchangeState => Observable.from(exchangeState.A))
.filter(marketData => marketData.Fills.length > 0)
.map(marketData => marketData && marketData.Fills)
Which works fine - when i connect to the client i flatMap to the subscription connection.
Then i have the candleObservable that is causing problems
export const candleObservable = (promise, timeFrame = TIME_FRAME) =>
promise
.scan((acc, curr) => [...acc, ...curr])
.skipWhile(exchangeData => dateDifferenceInSeconds(exchangeData) < timeFrame)
// take first after skipping
.first()
// first will complete the stream, so we repeat it
.repeat()
// we create candle data from the timeFrame array
.map(fillsData => createCandle(fillsData))
// accumulate candles
.scan((acc, curr) => [...[acc], curr])
What i am trying to achieve is to accumulate data until i have for a full candle that can be x seconds. Then i would like to take that emit and reset the scan function so i start for a new candle. Then i create the candle and accumulate it in another scan.
My problem is that when i call repeat() my socketObservable also gets called again. I do not know if this causes any overhead with the node-bittrex-api but i would like to avoid it.
I have tried putting the accumulating candle part in a flatMap or similar but couldn't get anyt of that to work.
Do you know how i can avoid to repeat() the whole stream or another way of make candles where i can accumulate and then reset the accumulator after first emit?
From what you've described it sounds like you have an observable you want to cut up into buckets of some kind based on some condition. In general, the reduction of a stream to another stream with fewer elements (without filtering) is referred to as "backpressure". In your specific case, it sounds like the backpressure operator you'd be interested in is buffer. The buffer operator can accept an observable as an argument that functions as a "closing selector", i.e. emissions in this observable can be used to regulate when you tie off one buffer and start a new one.
I'd suggest replacing your scan, skipWhile, first, and repeat with a buffer call, passing in a closing selector that will yield a value when your "TIME_FRAME" expires. This should be easy to express as an observable either using timer (in the case of a fixed amount) or a debounced version of the driving stream (if you want to stop when there's a pause in the data). If your buffer is strictly time-based, there's even a specialization of buffer called bufferTime that handles this. Because you'll wind up with an observable of arrays (rather than raw values), you'll likely want to replace your final scan with a regular array reduce.
It's hard to give concrete code without a simpler example to work with. I'd urge you to consult the sample code for the various backpressure operators to see if you can find something similar to what you're attempting to achieve.

How to access the data stored in this object?

I'm using BioPerl module to obtain a string from a set of parameters. I followed the HOWTO:Beginners page. The module apparently returns a hash object. How do I get the actual string out of the hash object?
use Bio::DB::GenBank;
use Data::Dumper;
my $gb = Bio::DB::GenBank->new(-format => 'Fasta',
-seq_start => 1,
-seq_stop => 251,
-strand => 1
-complexity => 1);
my $seq = $gb->get_Seq_by_acc('NG_016346');
my $sequence_string = lc($seq->seq());
my $seq_obj = Bio::Seq->new(-seq => $sequence_string,
-alphabet => 'dna' );
my $prot_obj = $seq_obj->translate;
print Dumper($prot_obj);
The data dumper prints the following:
$VAR1 = bless( {
'primary_seq' => bless( {
'length' => 83,
'_root_verbose' => 0,
'_nowarnonempty' => undef,
'seq' => 'RLCVKEGPWPAVEGTWSWG*HRPGSRACPRWGAPNSVQATSYTPSPTHAPFSVSPIPIC*MSLLEASCWPGSREDGARMSAGM',
'alphabet' => 'protein'
}, 'Bio::PrimarySeq' ),
'_root_verbose' => 0
}, 'Bio::Seq' );
How do I obtain 'seq' that is stored in $prot_obj?
I tried
print $prot_obj{'primary_seq'}{'seq'};
but it doesn't print anything. Data dumper printed the word bless. Maybe seq is a field of an object oriented variable.
The correct format for accessing object properties uses ->:
print $prot_obj->{'primary_seq'}->{'seq'};
I'm going to dispute the other answer, and say - the correct way to access object properties is not to do so, and use a method instead.
The reason for doing this is the whole point of OO. Which is to encapsulate chunks of your program, such that multiple developers can work with it concurrently, and the code scales because you can find where things are going wrong more easily.
This only works if you used published methods - the specified way of driving the object - because then you don't have to know what's going on behind the scenes. It also means the implementor is free to change what is going on - maybe simply validating, but maybe overloading or having different responses depending on another property within the object.
All this is subverted by direct access to object properties.
You shouldn't do it, even if perl will "let" you. Let's face it, perl will let you do many bad things.
Bio::PrimarySeq has a method call of seq. to retrieve the seq() attribute. Bio::Seq has an accessor for the primary sequence:
So:
$prot_obj -> seq();
I think would probably do it. (Although, the doc isn't exactly easy reading).
There is an accepted answer but I would also advise against poking around in the intervals of objects like that with the only exception being to see what kind of object is returned (or just use ref). Here is how I would approach the problem:
use 5.010;
use strict;
use warnings;
use Bio::DB::GenBank;
use Bio::Seq;
my $gb = Bio::DB::GenBank->new(
-format => 'Fasta',
-seq_start => 1,
-seq_stop => 251,
-strand => 1,
-complexity => 1
);
my $seq = $gb->get_Seq_by_acc('NG_016346');
my $seq_obj = Bio::Seq->new(
-id => $seq->id,
-seq => $seq->seq,
-alphabet => 'dna'
);
say join "\n", ">".$seq_obj->id, $seq_obj->translate->seq;
Running this gives you the translated FASTA record:
>gi|283837914:1-251
RLCVKEGPWPAVEGTWSWG*HRPGSRACPRWGAPNSVQATSYTPSPTHAPFSVSPIPIC*MSLLEASCWPGSREDGARMSAGM
The real benefit of using BioPerl is in combining the different classes together to solve problems with minimal (but also readable and reusable) code. There was also a minor typo in your code that would have been caught with strict and warnings pragmas enabled (that is my best advice).

Mongodb, using data context when update

I want to know is it possible that Use current data context when we update.
collection.update({_id: id},
{$set:
{'tmp.$.data': (function(){
return this.a + this.b})()},
{multi:true});
In the set operation, I tried to calculate something with IIFE function and 'this' keyword,
but there's nothing I can get as we expected, because that IIFE scope is placed outside of the update scope.
(a & b is an item in that object.)
That's what I want to do.
If we can control some data when we're doing update, I think it's really useful to manipulate collections.
Does anyone have idea about this?
Thanks in advance-
ps. I updated this question to js version.
Whenever I run into strangeness around # variables, I just make references outside of that closure. So from this:
collection.update (_id: id),
($set:
'tmp.$.data': do ->
return #a + #b),
(multi:true)
To this:
a = #a
b = #b
collection.update(
_id: id
$set:
'tmp.$.data': do ->
return a + b
multi:true
)
It seems like things can get goofed up when a function is expecting a function as an argument and get's something else. I'm not sure if that do in the tmp.$.data hash is really necessary either but I don't know meteor well enough to say yes or no.

How to maintain counters with LinqToObjects?

I have the following c# code:
private XElement BuildXmlBlob(string id, Part part, out int counter)
{
// return some unique xml particular to the parameters passed
// remember to increment the counter also before returning.
}
Which is called by:
var counter = 0;
result.AddRange(from rec in listOfRecordings
from par in rec.Parts
let id = GetId("mods", rec.CKey + par.UniqueId)
select BuildXmlBlob(id, par, counter));
Above code samples are symbolic of what I am trying to achieve.
According to the Eric Lippert, the out keyword and linq does not mix. OK fair enough but can someone help me refactor the above so it does work? A colleague at work mentioned accumulator and aggregate functions but I am novice to Linq and my google searches were bearing any real fruit so I thought I would ask here :).
To Clarify:
I am counting the number of parts I might have which could be any number of them each time the code is called. So every time the BuildXmlBlob() method is called, the resulting xml produced will have a unique element in there denoting the 'partNumber'.
So if the counter is currently on 7, that means we are processing 7th part so far!! That means XML returned from BuildXmlBlob() will have the counter value embedded in there somewhere. That's why I need it somehow to be passed and incremented every time the BuildXmlBlob() is called per run through.
If you want to keep this purely in LINQ and you need to maintain a running count for use within your queries, the cleanest way to do so would be to make use of the Select() overloads that includes the index in the query to get the current index.
In this case, it would be cleaner to do a query which collects the inputs first, then use the overload to do the projection.
var inputs =
from recording in listOfRecordings
from part in recording.Parts
select new
{
Id = GetId("mods", recording.CKey + part.UniqueId),
Part = part,
};
result.AddRange(inputs.Select((x, i) => BuildXmlBlob(x.Id, x.Part, i)));
Then you wouldn't need to use the out/ref parameter.
XElement BuildXmlBlob(string id, Part part, int counter)
{
// implementation
}
Below is what I managed to figure out on my own:.
result.AddRange(listOfRecordings.SelectMany(rec => rec.Parts, (rec, par) => new {rec, par})
.Select(#t => new
{
#t,
Id = GetStructMapItemId("mods", #t.rec.CKey + #t.par.UniqueId)
})
.Select((#t, i) => BuildPartsDmdSec(#t.Id, #t.#t.par, i)));
I used resharper to convert it into a method chain which constructed the basics for what I needed and then i simply tacked on the select statement right at the end.

Parallel.ForEach Ordered Execution

I am trying to execute parallel functions on a list of objects using the new C# 4.0 Parallel.ForEach function. This is a very long maintenance process. I would like to make it execute in the order of the list so that I can stop and continue execution at the previous point. How do I do this?
Here is an example. I have a list of objects: a1 to a100. This is the current order:
a1, a51, a2, a52, a3, a53...
I want this order:
a1, a2, a3, a4...
I am OK with some objects being run out of order, but as long as I can find a point in the list where I can say that all objects before this point were run. I read the parallel programming csharp whitepaper and didn't see anything about it. There isn't a setting for this in the ParallelOptions class.
Do something like this:
int current = 0;
object lockCurrent = new object();
Parallel.For(0, list.Count,
new ParallelOptions { MaxDegreeOfParallelism = MaxThreads },
(ii, loopState) => {
// So the way Parallel.For works is that it chunks the task list up with each thread getting a chunk to work on...
// e.g. [1-1,000], [1,001- 2,000], [2,001-3,000] etc...
// We have prioritized our job queue such that more important tasks come first. So we don't want the task list to be
// broken up, we want the task list to be run in roughly the same order we started with. So we ignore tha past in
// loop variable and just increment our own counter.
int thisCurrent = 0;
lock (lockCurrent) {
thisCurrent = current;
current++;
}
dothework(list[thisCurrent]);
});
You can see how when you break out of the parallel for loop you will know the last list item to be executed, assuming you let all threads finish prior to breaking. I'm not a big fan of PLINQ or LINQ. I honestly don't see how writing LINQ/PLINQ leads to maintainable source code or readability.... Parallel.For is a much better solution.
If you use Parallel.Break to terminate the loop then you are guarenteed that all indices below the returned value will have been executed. This is about as close as you can get. The example here uses For but ForEach has similar overloads.
int n = ...
var result = new double[n];
var loopResult = Parallel.For(0, n, (i, loopState) =>
{
if (/* break condition is true */)
{
loopState.Break();
return;
}
result[i] = DoWork(i);
});
if (!loopResult.IsCompleted &&
loopResult.LowestBreakIteration.HasValue)
{
Console.WriteLine("Loop encountered a break at {0}",
loopResult.LowestBreakIteration.Value);
}
In a ForEach loop, an iteration index is generated internally for each element in each partition. Execution takes place out of order but after break you know that all the iterations lower than LowestBreakIteration will have been completed.
Taken from "Parallel Programming with Microsoft .NET" http://parallelpatterns.codeplex.com/
Available on MSDN. See http://msdn.microsoft.com/en-us/library/ff963552.aspx. The section "Breaking out of loops early" covers this scenario.
See also: http://msdn.microsoft.com/en-us/library/dd460721.aspx
For anyone else who comes across this question - if you're looping over an array or list (rather than an IEnumberable ), you can use the overload of Parallel.Foreach that gives the element index to maintain original order too.
string[] MyArray; // array of stuff to do parallel tasks on
string[] ProcessedArray = new string[MyArray.Length];
Parallel.ForEach(MyArray, (ArrayItem,loopstate,ArrayElementIndex) =>
{
string ProcessedArrayItem = TaskToDo(ArrayItem);
ProcessedArray[ArrayElementIndex] = ProcessedArrayItem;
});
As an alternate suggestion, you could record which object have been run and then filter the list when you resume exection to exclude the objects which have already run.
If this needs to be persistent across application restarts, you can store the ID's of the already executed objects (I assume here the objects have some unique identifier).
For anybody looking for a simple solution, I have posted 2 extension methods (one using PLINQ and one using Parallel.ForEach) as part of an answer to the following question:
Ordered PLINQ ForAll
Not sure if question was altered as my comment seems wrong.
Here improved, basically remind that parallel jobs run in out of your control order.
ea printing 10 numbers might result in 1,4,6,7,2,3,9,0.
If you like to stop your program and continue later.
Problems alike this usually endup in batching workloads.
And have some logging of what was done.
Say if you had to check 10.000 numbers for prime or so.
You could loop in batches of size 100, and have a prime log1, log2, log3
log1= 0..99
log2=100..199
Be sure to set some marker to know if a batch job was finished.
Its a general aprouch since the question isnt that exact either.

Resources