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.
Related
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
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.
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)
;
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
I have this function that uses foldright to append the two lists
def append[T](l1: List[T], l2: List[T]): List[T] = (l1 :\ l2) ((a,b) => a::b)
The scala returns:
val l1 = List(1,2,3,4,5)
val l2 = List(6,7,8,9,10)
println(append(l1,l2))
Result: List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
As starting from right to left, the result should not return opposite? Why returns in this way?
foldRight is execute from right to left, so the iteration is,
1: a is 5, b is 6, 7, 8, 9, 10, result is 5, 6, 7, 8, 9, 10
2: a is 4, b is 5, 6, 7, 8, 9, 10, result is 4, 5, 6, 7, 8, 9, 10
...
final result is 1, 2, 3, ..., 8, 9, 10