Reputation: 12366
for (i <- Range(1,7); j <- Range(1,7))
yield (i,j) // want to yield only if there is no such a pair
Is it possible to have access to the list, formed by yield, inside the loop? For example, if I don't want to add duplicates.
P.S. The main question is not how to do it in this particular case. But how to avoid duplicates in more complex case, where I want to check, what was already yielded.
Upvotes: 1
Views: 349
Reputation: 36269
I'm not sure, whether you want to prevent pairs of identic entries, or identic pairs, ignoring which comes first.
In the second case, you might use an ordering, and just add cases where a < b or a <= b:
for (i <- Range(1,6); j <- Range(i+1, 7)) yield (i,j)
Upvotes: 1
Reputation: 13137
You cannot access members of an immutable collection being built from within the for comprehension.
First of all, I'm going to modify your example so it actually produces duplicates:
for (i <- Range(1,3); j <- Range(1,3)) yield (i min j, i max j)
//scala.collection.immutable.IndexedSeq[(Int, Int)] = Vector((1,1), (1,2), (1,2), (2,2))
For comprehensions are just syntactic sugar, so here's the equivalent using map
and flatMap
that produces the exact same result
Range(1,3).flatMap{i => Range(1,3).map{ j => (i min j, i max j)}}
As you can see, you're not actually building a single collection, but rather a collection of collections, and then merging them together as they're created. The inner map
is taking each j
in the range and mapping it to a pair, then the outer flatMap
is mapping each i
to a sequence of pairs and merging them together. If I change the flatMap
to just map
, the result is this:
Range(1,3).map{i => Range(1,3).map{ j => (i min j, i max j)}}
//Vector(Vector((1,1), (1,2)), Vector((1,2), (2,2)))
So only after the whole operation is finished can you access the result as a single collection. The result is a Vector which extends IndexedSeq[(Int, Int)]
, so you can use any of that trait's methods on the result, one of them is distinct
:
(for (i <- Range(1,3); j <- Range(1,3)) yield (i min j, i max j)).distinct
//Vector((1,1), (1,2), (2,2))
Upvotes: 3
Reputation: 67330
Like this
for (i <- Range(1,7); j <- Range(1,7); if i != j ) yield (i,j)
or this
for (i <- Range(1,7); j <- Range(1,7); if i < j ) yield (i,j)
?
Upvotes: 2
Reputation: 27270
(for {i <- (1 to 7); j <- (1 to 7)} yield (i,j)).distinct
This would return list of tuples without duplicates.
And no, there is no way to have access to the list inside for
loop. That would break the functional programming, after all.
Upvotes: 1