Calculate the Cartesian product (xprod method) of two Observables - reactive-programming

I have one interesting question. Maybe anybody know how could I implement a method like a http://ramdajs.com/docs/#xprod. I have one solution which I found:
let as = [1, 2, 3];
let bs = ['a', 'b', 'c'];
Rx.Observable.for(bs, b => {
return Rx.Observable.for(as, a => Rx.Observable.just([a, b]));
}).toArray().subscribe(x => {
console.log(x.sort((a, b) => a[0] - b[0]));
});

I agree with Ben Lesh's comment above that, unless there's something async going on, you probably don't need to use an Observable.
A plain ES5, array-based solution (which is equivalent to Matt Podwysocki's inner map solution) could look like:
var as = [1, 2, 3],
bs = ['a', 'b', 'c'];
as.flatMap = flatMap;
var product = as.flatMap(pairWithAllBs);
// pairWithAllBs :: Number -> [[Number, String]]
function pairWithAllBs(a) {
return bs.map(function (b) {
return [a, b];
});
}
// flatMap :: #[a], (a -> [b]) -> [b]
// JS does not have a built-in flatMap function.
function flatMap(fn) {
return Array.prototype.concat.apply([], this.map(fn));
}
In ES7, using array comprehensions, we should be able to just do:
[for (a of as) for (b of bs) [a, b]];

Related

How to compare two arrays and find the indices where the elements differ?

Is there any builtin function in Scala (not able to fetch indexes after comparing)?
Here is some JavaScript code I already have:
var diffIndexes = [];
var newTags = ['a','b','c'];
var oldTags = ['c'];
var diffValues = arrayDiff(newTags, oldTags);
console.log(diffIndexes); // [0, 1]
console.log(diffValues); // ['a', 'b'] "
You can do it really easy using zipWithIndex, and unzip
val (diffValues, diffIndexes) = newTags.zipWithIndex.filter(c => !oldTags.contains(c._1)).unzip
Code run at Scastie
You can do something as follows:
def arrayDiff[T](newTags: List[T], oldTags: List[T]) = {
oldTags.foldLeft(newTags.zipWithIndex.toMap) {
case (seed, char) => {
seed.get(char) match {
case Some(_) => seed - char
case _ => seed
}
}
}
}
val newTags = List('a', 'b', 'c')
val oldTags = List('c')
val (diffIndexes, diffValues) = arrayDiff(newTags, oldTags).unzip
println(diffIndexes) // List(a, b)
println(diffValues) // List(0, 1)
I'm not sure if that what you meant, since what you want to do when oldTags has some values that newTags not?, In my case scenario - its will ignore the oldTag since its not in the newTags

Use an array as a Scala foldLeft accumulator

I am trying to use a foldLeft on an array. Eg:
var x = some array
x.foldLeft(new Array[Int](10))((a, c) => a(c) = a(c)+1)
This refuses to compile with the error found Int(0) required Array[Int].
In order to use foldLeft in what you want to do, and following your style, you can just return the same accumulator array in the computation like this:
val ret = a.foldLeft(new Array[Int](10)) {
(acc, c) => acc(c) += 1; acc
}
Alternatively, since your numbers are from 0 to 9, you can also do this to achieve the same result:
val ret = (0 to 9).map(x => a.count(_ == x))
Assignment in Scala does not return a value (but instead Unit) so your expression that is supposed to return the Array[Int] for the next step returns Unit which does not work.
You would have to use a block and return the array in the end like this:
x.foldLeft(new Array[Int](10)) { (a, c) =>
a(c) = a(c)+1
a
}

Using maps in Scala

val nums = Map('M' -> 1000, 'D' -> 500, 'C' -> 100, 'L' -> 50, 'X' -> 10, 'V' -> 5, 'I' -> 1)
def convert(data : String):Int = {
var count = 0;
var index = 0;
var list: List[Char] = List();
for((value,index) <- data.reverse.zipWithIndex){
list = value :: list;
}
def calcRM(rm : List[Char]): List[Char] = rm match{
case x :: Nil => x
case x :: tail => ???
case Nil => Nil
}
return count
}
}
I am wondering how I can convert the value I get from x(head) and tail.head by using the Map provided so I can convert the string to the value in Roman Numerals.
To access a map, you simply use its get method:
nums.get(x)
which returns an Option that you would have to unwrap, so you can assume all good values and use the apply:
nums(x) //Throws if key not found
or you could use a default:
nums.getOrElse(x, 0)
You are looking for the apply method on Map. Recall that you can call apply simply by adding parentheses:
nums('M') //returns 1000
nums.apply('M') //equivalent in Scala
You can also use get to return an Option[Int] if you aren't sure the key is available in the Map, and you want to avoid the exception that would otherwise be thrown by apply:
nums.get('M') //returns Some(1000)
nums.get('K') //returns None
nums('K') //throws an exception
I would also recommend looking into some of the more idiomatic paradigms in Scala (e.g. using val). For your example, you might consider something like this, which uses inner methods and values, slightly more complex pattern matching, the ever important map method, the implicit apply used in the map, and recursion:
def convert(rm: String) = {
val nums = Map('M' -> 1000, 'D' -> 500, 'C' -> 100, 'L' -> 50, 'X' -> 10, 'V' -> 5, 'I' -> 1)
def calcRM(rm: Seq[Int]): Int = rm match {
case x :: y :: tail if x < y => y - x + calcRM(tail)
case x :: tail => x + calcRM(tail)
case Nil => 0
}
calcRM(rm.map(nums).toList)
}

Is there an Rx operator for combining the latest from streams 1 and 2 only when stream 2 emits things?

Here's my attempt at drawing the marble diagram --
STREAM 1 = A----B----C---------D------>
(magical operator)
STREAM 2 = 1----------2-----3-----4--->
STREAM 3 = 1A---------2C----3C----4D-->
I am basically looking for something that generates stream 3 from streams 1 and 2. Basically, whenever something is emitted from stream 2, it combines it with the latest from stream 1. combineLatest is similar to what I want but I only want things emitted from stream 3 when something is emitted from stream 2, not stream 1. Does an operator like this exist?
There is an operator that does what you need: One overload of sample takes another observable instead of duration as a parameter. The documentation is here: https://github.com/ReactiveX/RxJava/wiki/Filtering-Observables#sample-or-throttlelast
The usage (I'll give examples in scala):
import rx.lang.scala.Observable
import scala.concurrent.duration
import duration._
def o = Observable.interval(100.milli)
def sampler = Observable.interval(180.milli)
// Often, you just need the sampled observable
o.sample(sampler).take(10).subscribe(x ⇒ println(x + ", "))
Thread.sleep(2000)
// or, as for your use case
o.combineLatest(sampler).sample(sampler).take(10).subscribe(x ⇒ println(x + ", "))
Thread.sleep(2000)
The output:
0,
2,
4,
6,
7,
9,
11,
13,
15,
16,
(2,0),
(4,1),
(6,2),
(7,3),
(9,4),
(11,5),
(13,6),
(15,7),
(16,8),
(18,9),
There is a slight catch in that duplicate entries from the sampled observable are swallowed (see discussion at https://github.com/ReactiveX/RxJava/issues/912). Other than that, I think it is exactly what you are looking for.
withLatestFrom seems to fit exactly what I was looking for - http://rxmarbles.com/#withLatestFrom
As far as I know there isn't a single existing operator that will do what you want. However you can compose one by using CombineLatest and DistinctUntilChanged as follows:
var joined = Observable.CombineLatest(sourceA, sourceB, (a,b) => new { A = a, B = b })
.DistinctUntilChanged(pair => pair.B);
EDIT:
The above will work as long as the values for STREAM 1 change each time. If they do not, then then use the following, which is less clear, but works in all situations (that I've tested anyway).
var joined = Observable.Join(
sourceB,
sourceA,
_ => Observable.Return(Unit.Default),
_ => sourceA,
(a, b) => new { A = a, B = b });
The Join operator is never intuitive to me, the best explanation I've found is here.
In answer to #Matthew's comment
var buttonClicks = Observable.FromEventPattern<MouseButtonEventArgs>(this,
"MouseLeftButtonDown")
.Select(_ => Unit.Default);
var sequence = Observable.Interval(TimeSpan.FromSeconds(1));
var joined = Observable.Join(
buttonClicks,
sequence,
_ => Observable.Return(Unit.Default),
_ => sequence,
(b, s) => s); // No info in button click here
Here is a fairly simple way to do it:
var query = stream2.Zip(
stream1.MostRecent(' '),
(s2,s1) => string.Format("{0}{1}", s2, s1));
MostRecent can be supplied a "zero" value which is used in the event stream1 has not emitted yet. This could be null for reference types, but I used a char for stream1 so supplied a space.
I think that the Switch operator is the key here.
Try this:
var query =
stream1
.Select(s1 => stream2.Select(s2 => new { s1, s2 }))
.Switch();
The following test code:
query
.Select(s => String.Format("{0}{1}", s.s2, s.s1))
.Subscribe(Console.WriteLine);
stream1.OnNext('A');
stream2.OnNext(1);
stream1.OnNext('B');
stream1.OnNext('C');
stream2.OnNext(2);
stream2.OnNext(3);
stream1.OnNext('D');
stream2.OnNext(4);
Gives these results:
1A
2C
3C
4D
Please let me know if this is correct.
A solution
public static IObservable<TR> Sample<TSource, TSampler, TR>
(this IObservable<TSource> source,
IObservable<TSampler> sampler,
Func<TSource, TSampler, TR> combiner)
{
return source.Publish
(rs => sampler
.Zip
( rs.MostRecent(default(TSource))
, (samplerElement, sourceElement)
=> combiner(sourceElement, samplerElement)
)
.SkipUntil(rs)
);
}
with a test case because this kind of thing is tricky to get right.
public class SampleSpec : ReactiveTest
{
TestScheduler _Scheduler = new TestScheduler();
[Fact]
public void ShouldWork()
{
var sampler = _Scheduler.CreateColdObservable
( OnNext(10, "A")
, OnNext(20, "B")
, OnNext(30, "C")
, OnNext(40, "D")
, OnNext(50, "E")
, OnNext(60, "F")
);
var source = _Scheduler.CreateColdObservable
( Enumerable
.Range(5,100)
.Where(i=>i%10!=0)
.Select(i=>OnNext(i,i)).ToArray());
var sampled = source.Sample
(sampler, Tuple.Create);
var actual = _Scheduler.Start
(() =>
sampled
, created: 0
, subscribed: 1
, disposed: 1000);
actual.Messages.Count()
.Should()
.Be(6);
var messages = actual.Messages.Take(6)
.Select(v => v.Value.Value)
.ToList();
messages[0].Should().Be(Tuple.Create(9,"A"));
messages[1].Should().Be(Tuple.Create(19,"B"));
messages[2].Should().Be(Tuple.Create(29, "C"));
messages[3].Should().Be(Tuple.Create(39, "D"));
messages[4].Should().Be(Tuple.Create(49, "E"));
messages[5].Should().Be(Tuple.Create(59, "F"));
}
}

Returning values from an inner loop in Scala, use a function instead?

I'm attempting to return a value from a inner loop. I could create a outside list
and populate it within the inner loop as suggested in comments below but this does
not feel very functional. Is there a function I can use to achieve this ?
The type of the loop/inner loop is currently Unit but I would like it to be of type List[Int] or some similar collection type.
val data = List(Seq(1, 2, 3, 4), Seq(1, 2, 3, 4))
//val list : List
for(d <- data){
for(d1 <- data){
//add the result to the val list defined above
distance(d , d1)
}
}
def distance(s1 : Seq[Int], s2 : Seq[Int]) = {
s1.zip(s2).map(t => t._1 + t._2).sum
}
val list = for (x <- data; y <- data) yield distance(x, y)
will do what you want, yielding:
List(20, 20, 20, 20)
The above desugared is equivalent to:
data.flatMap { x => data.map { y => distance(x, y) } }
The trick is to not nest for-comprehensions because that way you'll only ever get nested collections; to get a flat collection from a conceptually nested iteration, you need to make sure flatMap gets used.