How can I merge 2 observables in a custom fashion? - rx-java2

Custom fashion is:
obs1 = [1, 3, 5, 7, 9], obs2 = [2, 4, 6, 8, 10] -> mergedObs = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
I was thinking about obs1.zipWith(obs2) and my bifunction was (a, b) -> Observable.just(a, b) and then it's not trivial for me to flatten Observable<Observable<Integer>>.

That looks like an ordered merge: merge so that the smallest is picked from the sources when they all have items ready:
Flowables.orderedMerge():
Given a fixed number of input sources (which can be self-comparable or given a Comparator) merges them into a single stream by repeatedly picking the smallest one from each source until all of them completes.
Flowables.orderedMerge(Flowable.just(1, 3, 5), Flowable.just(2, 4, 6))
.test()
.assertResult(1, 2, 3, 4, 5, 6);
Edit
If the sources are guaranteed to be the same length, you can also zip them into a structure and then flatten that:
Observable.zip(source1, source2, (a, b) -> Arrays.asList(a, b))
.flatMapIterable(list -> list)
;

Related

Get items from seq traits in Scala

I'm looking for an elegant way to get elements by generated array consisting of indices
create a seq
val nums = Seq(1, 2, 3, 4, 5, 7, 9, 11, 14, 12, 16)
create a slice
val i = Array.range(2, 10, 3)
Array[Int] = Array(2, 5, 8)
How to get 3, 7, 14 from Seq?
If I understood correctly, you want to pick elements from nums corresponding to indexes from i.
The most elegant way I can think of it:
i.map(nums.apply)
scastie: https://scastie.scala-lang.org/KacperFKorban/ckwx5KMKQMOss1L0ce661w

Intersection of Sets in Scala

I have a HashMap of the following form in Scala:
HashMap(
37 -> HashSet(5, 1, 6, 9, 13, 12, 3, 8, 4),
20 -> HashSet(5, 1, 6, 9, 13, 12, 3, 8, 4),
45 -> HashSet(5, 6, 9, 13, 3, 8, 4),
49 -> HashSet(5, 6, 9, 13, 3, 8, 4),
39 -> Set(5, 12, 3, 9),
31 -> HashSet(5, 6, 9, 13, 3, 8, 4),
15 -> Set(5, 9, 3),
28 -> Set(5, 3, 9),
21 -> HashSet(5, 6, 9, 13, 3, 8, 4),
33 -> Set(9, 3),
40 -> HashSet(5, 1, 6, 9, 13, 12, 3, 8, 4),
26 -> Set(9, 3, 5),
55 -> Set(6, 4, 8),
23 -> Set(9, 5, 3, 12),
36 -> Set(7, 2),
19 -> Set(5, 9, 3))
What is the most efficient way to get the intersection of all Sets in the Map?
The problem is that these map and sets might grow large and the intersection is needed abundantly in a recursive algorithm (up to 10K calls in one execution) and the For comprehension in Scala is not doing the trick efficiently.
Edit :
As for For comprehension I just did a simple function to compute it (it has one non useful intersection that could be optimized, the first one, irrelevant to the high number of calls. I could also stop the computation once the intersection is empty but it rarely happens but I am avoiding the intersection of empty values since theoretically in my algorithm, the Map should not have keys with empty values :
def stateIntersection(m: Map[Int, Set[Int]]): Set[Int] = {
var acc = m.head._2
for ((k, v) <- m) {
if (v.nonEmpty)
acc = acc.intersect(v)
}
acc
}
Do the values in your sets have lower and upper bounds? In case they do, and the range is reasonably small (say, 0..1000), an efficient way (in any language) could be to create a fixed size array int[0..1000], then iterate over all sets and increment the corresponding array element. This is a constant time operation unlike searching in a set, which would be inevitably part of the algorithm above.
counters = int[1000] // assuming it's initialized with 0's
for set in sets {
for element in set.elements {
counters[element]++
}
}
Then you simply collect the array elements with the values equal to the number of sets.

Can you merge two Flux, without blocking, such that the result only contains unique elements?

Is there a way to merge two Flux such that the result only contains unique elements? I can block on the output and then convert it to a set, but is there a way that does not depend on blocking?
Source (Kotlin)
val set1 = Flux.just(1, 2, 3, 4, 5)
val set2 = Flux.just(2, 4, 6, 8, 10)
val mergedSet = set1.mergeWith(set2)
println(mergedSet.collectList().block())
Output
[1, 2, 3, 4, 5, 2, 4, 6, 8, 10]
Desired Output (order is not important)
[1, 2, 3, 4, 5, 6, 8, 10]
You can use the Flux's merge method and then apply distinct() to it.
Flux.merge (Flux.just(1, 2, 3, 4, 5), Flux.just(2, 4, 6, 8, 10)).distinct();
This way you get a flux which produces only distinct values.

Do you have any idea or documentation about why we have arc4random_stir() in swift?

I have written the program below for generating random unique numbers for several number of times by invoking the function, but it seems like I'm getting the same pattern with minimal changes.
func generateRandom(withinNumber: Int) {
var i:Int = 0
var elements = Set<Int>()
while i != withinNumber {
let num:Int = Int(arc4random())%withinNumber + 1
if elements.count <= withinNumber && elements.contains(num) == false {
elements.insert(num)
}
else {
i = i-1
}
i=i+1
}
print(elements)
elements.removeAll()
}
generateRandom(withinNumber: 10)
How does I make my program effectively run to generate several random unique numbers.
Please let me know it would be very helpful for me.
You are storing your numbers in a Set and sets are not ordered, so the order the elements are shown by print is unrelated to the order in which they were added to the set.
Rather the elements of a set are stored in some manner which enables fast checking for .contains(), and this is one reason you seeing similar sequences.
If you wish to preserve order of insertion use a collection which does this, i.e. an array. Changing to an array in your code produced the following results from 9 calls:
[8, 9, 7, 10, 5, 6, 2, 3, 1, 4]
[4, 9, 10, 3, 6, 2, 1, 7, 8, 5]
[8, 3, 5, 1, 6, 4, 9, 10, 7, 2]
[5, 7, 2, 9, 8, 1, 6, 10, 3, 4]
[2, 3, 7, 6, 9, 1, 8, 10, 5, 4]
[9, 10, 2, 4, 6, 8, 5, 7, 1, 3]
[9, 10, 2, 5, 4, 7, 3, 8, 1, 6]
[1, 6, 4, 5, 8, 2, 3, 9, 7, 10]
[6, 10, 5, 3, 2, 8, 1, 9, 7, 4]
You are also generating 10 random numbers in the range 1 to 10 and avoiding duplicates, so the results is always going to be the numbers 1 to 10 in some order.
To generate a random number in a given range do not use %, instead use the provided arc4random_uniform() which will give better a better distribution.
The function mention in your title arc4random_stir() is available in Swift.
BTW (somewhat opinion based): It is better to write !e (! being the boolean not operator) rather than e == false, and never ever write e == true which is the long form of e!
BTW (SO etiquette): Don't link to your code (or paste in images of it). Reduce to a small example which demonstrates the issue (not required in your case) and insert directly in the question. Keep tags minimal and appropriate. These edits were done for you this time by myself and others, you will know for next time.
HTH

Remove unique items from sequence [duplicate]

This question already has answers here:
How to get a set of all elements that occur multiple times in a list in Scala?
(2 answers)
Closed 8 years ago.
I find a lot about how to remove duplicates, but what is the most elegant way to remove unique items first and then the remaining duplicates.
E.g. a sequence (1, 2, 5, 2, 3, 4, 4, 0, 2) should be converted into (2, 4).
I can think of using a for-loop to add a count to each distinct item, but I could imagine that Scala has a more elegant way to achieve this.
distinct and diff will works for you:
val a = List(1, 2, 5, 2, 3, 4, 4, 0, 2)
> a: List[Int] = List(1, 2, 5, 2, 3, 4, 4, 0, 2)
val b = a diff a.distinct
> b: List[Int] = List(2, 4, 2)
val c = (a diff a.distinct).distinct
> c: List[Int] = List(2, 4)
In place distinct you can use toSet as well.
Also keep in mind that i => i can be replaced by identity and map(_._1) by keys, like this:
Seq(1, 2, 5, 2, 3, 4, 4, 0, 2).groupBy(identity).filter(_._2.size > 1).keys.toSeq
This is where a countByKey method, such as the one that can be found in Spark's API, would be useful.
Pretty straight forward:
Seq(1, 2, 5, 2, 3, 4, 4, 0, 2).groupBy(i => i).filter(_._2.size > 1).map(_._1).toSeq
Using the link from Ende Neu I think your code would become this:
Seq(1, 2, 5, 2, 3, 4, 4, 0, 2).groupBy(identity).collect { case (v, l) if l.length > 1 => v } toSeq