why List.dropWhile doesn't work? - scala

Given code:
val test = List(1, 2, 3)
printList[Int](test.dropWhile((a: Int) => {a == 1}))
And it will print correctly: 2 3
While using code like this:
val test = List(1, 2, 3)
printList[Int](test.dropWhile((a: Int) => {a == 2}))
And it will print incorrectly: 1 2 3
And so does a == 3
How do I use dropWhile appropriately?
well, I figure out that dropWhile return "the longest suffix of this list whose first element does not satisfy the predicate p."
So if I want to detele some elements satisfy predicate p, I have to use filterNot : )

That's because dropWhile
drops longest prefix of elements that satisfy a predicate.
That is, it stops dropping as long as the condition is no longer met. In your second example it's not met from start, hence nothing is dropped.
You might be better off with a filter (which selects all elements satisfying a predicate) or filterNot (which selects all element NOT satisfying a predicate):
val test = List(1, 2, 3)
printList[Int](test.filterNot((a: Int) => {a == 2}))
or
val test = List(1, 2, 3)
printList[Int](test.filter((a: Int) => {a != 2}))

Related

Using span function to bisect a Map in Scala

I have a Map of the form [Int, Option[/* of some type that I am using */], thus:
scala> val t1: Map[Int,Option[(String,List[Int])]] = Map(500->Some("A",List(1,2,3)))
t1: Map[Int,Option[(String, List[Int])]] = Map(500 -> Some((A,List(1, 2, 3))))
scala> t1 + (400 -> Some("B",List(9,8,7))) + (300 -> None) + (200 -> None)
res6: scala.collection.immutable.Map[Int,Option[(String, List[Int])]] = Map(500 -> Some((A,List(1, 2, 3))), 400 -> Some((B,List(9, 8, 7))), 300 -> None, 200 -> None)
Now, I am trying to cleave into two maps, one having all the empty Values -from eponymous Key/Value - and the other having none of them, thus:
res6.span(e => e._2.isEmpty)
res7: (scala.collection.immutable.Map[Int,Option[(String, List[Int])]], scala.collection.immutable.Map[Int,Option[(String, List[Int])]]) = (Map(),Map(500 -> Some((A,List(1, 2, 3))), 400 -> Some((B,List(9, 8, 7))), 300 -> None, 200 -> None))
I am failing to understand why I am getting an empty Map on the left, while the < K,None > pairs are sitting blissfully inside the Map on the right. They should have been in the Map on the left, or so I expect.
What is the obvious thing that I am missing?
You should use partition instead of span.
Note: c span p is equivalent to (but possibly more efficient than) (c takeWhile p, c dropWhile p), provided the evaluation of the predicate p does not cause any side-effects.
So, span would stop scanning if the condition is not met.
For example,
scala> val l = List(1, 9, 8, 0)
scala> l.span(e => e < 2)
res7: (List[Int], List[Int]) = (List(1),List(9, 8, 0))
scala> l.partition(e => e < 2)
res8: (List[Int], List[Int]) = (List(1, 0),List(9, 8))
Note that, actually for span, it might return different results for different runs, unless the underlying collection type is ordered.
In your case, the first element in map may not None. (Map is not ordered)
By definition when you use span we get a Tuple2 of sequences that are of the same type as the original collection, one contain true values and other false values.
def span(p: A => Boolean): (Repr, Repr) =
In your case
res6.span(e => e._2.isEmpty)
So in your case you have a empty and non-empty elements of Tuple2.
If you wish to get non-empty values you use simply use _2 as
val nonEmptyValue = res6.span(e => e._2.isEmpty)._2

Scala get next index in the list from current item

Say for example I am mapping one list to the next, and in the map I want to do some calculation with the current item in the list with the next item in the list.
def someFunc(L: List[Integer]) : List[Integer] = {
L.collect {
case k if (k != L(L.length-1)) //do something with k and the next element
}
}
A simple example is I want to go through this List of Integers, and map each number onto the next number in the list divided by it.
E.g. (1,2,3) -> (2/1, 3/2) == (2, 1.5)
I had thought about doing this using indexOf but I don't think that is efficient having to search the whole list for the current element even though I am already traversing each element in the list anyway.
Use .sliding for this:
scala> val l = List(1, 2, 3)
l: List[Int] = List(1, 2, 3)
scala> l.sliding(2).toList
res0: List[List[Int]] = List(List(1, 2), List(2, 3))
scala> l.sliding(2).collect { case x::y::Nil if y != 0 => x / y.toDouble }.toList
res1: List[Double] = List(0.5, 0.6666666666666666)

Reverse list of n elements

i was given this problem and i thought I had it figured out , but i was told i had it wrong. the question was,. Given a list xs, reverse the first n elements. I guess im not understanding what the question was asking , i thought we take an Int n , and return the first n elements in front of that int n in reverse.
def nthRev[T](n: Int,xs: List[T]): List[T] = xs match {
case List() => List()
case head :: rest => (head::rest.take(n)).reverse
}
so, the output is
nthRev(3,List(1, 2, 3, 4, 5))
returns
List(4, 3, 2, 1)
but apparently its wrong, can anyone explain what the question is asking for?
The way I interpret your question "Given a list xs, reverse the first n elements." and the example
nthRev(3,List(1, 2, 3, 4, 5))
I would expect it to reverse the first 3 elements, but then leave the rest of the list:
List(3, 2, 1, 4, 5)
When the question says "first n elements" it is saying to replace "n" with the number given as the first argument in your example "3", to give "first 3 elements". The 3 has nothing to do with the element in the list. Changing your example:
nthRev(3,List(10,11,12,13,14)
would return
List(12,11,10,13,14)
I think it means you're supposed to return a new list that has the same elements of the original list, but with the first n elements reversed.
def nthRev[T](n: Int, xs: List[T]): List[T] =
xs.splitAt(n) match { case (a, b) => a.reverse ::: b }
nthRev(3, (1 to 5).toList) // List(3, 2, 1, 4, 5)
I would go with simple standard API. Have a look at the drop function explained in this post: Skip first N elements in scala iterable
def reverseAtN[a](n: Int, list: List[a]): List[a] =
List.concat(x.take(n).reverse, x.drop(n))

Finding an item that matches predicate in Scala

I'm trying to search a scala collection for an item in a list that matches some predicate. I don't necessarily need the return value, just testing if the list contains it.
In Java, I might do something like:
for ( Object item : collection ) {
if ( condition1(item) && condition2(item) ) {
return true;
}
}
return false;
In Groovy, I can do something like:
return collection.find { condition1(it) && condition2(it) } != null
What's the idiomatic way to do this in Scala? I could of course convert the Java loop style to Scala, but I feel like there's a more functional way to do this.
Use filter:
scala> val collection = List(1,2,3,4,5)
collection: List[Int] = List(1, 2, 3, 4, 5)
// take only that values that both are even and greater than 3
scala> collection.filter(x => (x % 2 == 0) && (x > 3))
res1: List[Int] = List(4)
// you can return this in order to check that there such values
scala> res1.isEmpty
res2: Boolean = false
// now query for elements that definitely not in collection
scala> collection.filter(x => (x % 2 == 0) && (x > 5))
res3: List[Int] = List()
scala> res3.isEmpty
res4: Boolean = true
But if all you need is to check use exists:
scala> collection.exists( x => x % 2 == 0 )
res6: Boolean = true
Testing if value matching predicate exists
If you're just interested in testing if a value exists, you can do it with.... exists
scala> val l=(1 to 4) toList
l: List[Int] = List(1, 2, 3, 4)
scala> l exists (_>5)
res1: Boolean = false
scala> l exists (_<2)
res2: Boolean = true
scala> l exists (a => a<2 || a>5)
res3: Boolean = true
Other methods (some based on comments):
Counting matching elements
Count elements that satisfy predicate (and check if count > 0)
scala> (l count (_ < 3)) > 0
res4: Boolean = true
Returning first matching element
Find the first element that satisfies predicate (as suggested by Tomer Gabel and Luigi Plinge this should be more efficient because it returns as soon as it finds one element that satisfies the predicate, rather than traversing the whole List anyway)
scala> l find (_ < 3)
res5: Option[Int] = Some(1)
// also see if we found some element by
// checking if the returned Option has a value in it
scala> l.find(_ < 3) isDefined
res6: Boolean = true
Testing if exact value exists
For the simple case where we're actually only checking if one specific element is in the list
scala> l contains 2
res7: Boolean = true
The scala way would be to use exists:
collection.exists(item => condition1(item) && condition2(item))
And since java 8 you can use anyMatch:
collection.stream().anyMatch(item -> condition1(item) && condition2(item));
which is much better than a plain for or foreach.
Filter and exists keywords to get the matching values from Lists
val values = List(1,2,3,4,5,6,7,8,9,10,....,1000) //List -1
val factors= List(5,7) // List -2
//To get the factors of List-2 from List-1
values .filter(a => factors.exists(b => a%b == 0)) //Apply different logic for our convenience
Given code helps to get the matching values from 2 different lists

Listing combinations WITH repetitions in Scala

Trying to learn a bit of Scala and ran into this problem. I found a solution for all combinations without repetions here and I somewhat understand the idea behind it but some of the syntax is messing me up. I also don't think the solution is appropriate for a case WITH repetitions. I was wondering if anyone could suggest a bit of code that I could work from. I have plenty of material on combinatorics and understand the problem and iterative solutions to it, I am just looking for the scala-y way of doing it.
Thanks
I understand your question now. I think the easiest way to achieve what you want is to do the following:
def mycomb[T](n: Int, l: List[T]): List[List[T]] =
n match {
case 0 => List(List())
case _ => for(el <- l;
sl <- mycomb(n-1, l dropWhile { _ != el } ))
yield el :: sl
}
def comb[T](n: Int, l: List[T]): List[List[T]] = mycomb(n, l.removeDuplicates)
The comb method just calls mycomb with duplicates removed from the input list. Removing the duplicates means it is then easier to test later whether two elements are 'the same'. The only change I have made to your mycomb method is that when the method is being called recursively I strip off the elements which appear before el in the list. This is to stop there being duplicates in the output.
> comb(3, List(1,2,3))
> List[List[Int]] = List(
List(1, 1, 1), List(1, 1, 2), List(1, 1, 3), List(1, 2, 2),
List(1, 2, 3), List(1, 3, 3), List(2, 2, 2), List(2, 2, 3),
List(2, 3, 3), List(3, 3, 3))
> comb(6, List(1,2,1,2,1,2,1,2,1,2))
> List[List[Int]] = List(
List(1, 1, 1, 1, 1, 1), List(1, 1, 1, 1, 1, 2), List(1, 1, 1, 1, 2, 2),
List(1, 1, 1, 2, 2, 2), List(1, 1, 2, 2, 2, 2), List(1, 2, 2, 2, 2, 2),
List(2, 2, 2, 2, 2, 2))
Meanwhile, combinations have become integral part of the scala collections:
scala> val li = List (1, 1, 0, 0)
li: List[Int] = List(1, 1, 0, 0)
scala> li.combinations (2) .toList
res210: List[List[Int]] = List(List(1, 1), List(1, 0), List(0, 0))
As we see, it doesn't allow repetition, but to allow them is simple with combinations though: Enumerate every element of your collection (0 to li.size-1) and map to element in the list:
scala> (0 to li.length-1).combinations (2).toList .map (v=>(li(v(0)), li(v(1))))
res214: List[(Int, Int)] = List((1,1), (1,0), (1,0), (1,0), (1,0), (0,0))
I wrote a similar solution to the problem in my blog: http://gabrielsw.blogspot.com/2009/05/my-take-on-99-problems-in-scala-23-to.html
First I thought of generating all the possible combinations and removing the duplicates, (or use sets, that takes care of the duplications itself) but as the problem was specified with lists and all the possible combinations would be too much, I've came up with a recursive solution to the problem:
to get the combinations of size n, take one element of the set and append it to all the combinations of sets of size n-1 of the remaining elements, union the combinations of size n of the remaining elements.
That's what the code does
//P26
def combinations[A](n:Int, xs:List[A]):List[List[A]]={
def lift[A](xs:List[A]):List[List[A]]=xs.foldLeft(List[List[A]]())((ys,y)=>(List(y)::ys))
(n,xs) match {
case (1,ys)=> lift(ys)
case (i,xs) if (i==xs.size) => xs::Nil
case (i,ys)=> combinations(i-1,ys.tail).map(zs=>ys.head::zs):::combinations(i,ys.tail)
}
}
How to read it:
I had to create an auxiliary function that "lift" a list into a list of lists
The logic is in the match statement:
If you want all the combinations of size 1 of the elements of the list, just create a list of lists in which each sublist contains an element of the original one (that's the "lift" function)
If the combinations are the total length of the list, just return a list in which the only element is the element list (there's only one possible combination!)
Otherwise, take the head and tail of the list, calculate all the combinations of size n-1 of the tail (recursive call) and append the head to each one of the resulting lists (.map(ys.head::zs) ) concatenate the result with all the combinations of size n of the tail of the list (another recursive call)
Does it make sense?
The question was rephrased in one of the answers -- I hope the question itself gets edited too. Someone else answered the proper question. I'll leave that code below in case someone finds it useful.
That solution is confusing as hell, indeed. A "combination" without repetitions is called permutation. It could go like this:
def perm[T](n: Int, l: List[T]): List[List[T]] =
n match {
case 0 => List(List())
case _ => for(el <- l;
sl <- perm(n-1, l filter (_ != el)))
yield el :: sl
}
If the input list is not guaranteed to contain unique elements, as suggested in another answer, it can be a bit more difficult. Instead of filter, which removes all elements, we need to remove just the first one.
def perm[T](n: Int, l: List[T]): List[List[T]] = {
def perm1[T](n: Int, l: List[T]): List[List[T]] =
n match {
case 0 => List(List())
case _ => for(el <- l;
(hd, tl) = l span (_ != el);
sl <- perm(n-1, hd ::: tl.tail))
yield el :: sl
}
perm1(n, l).removeDuplicates
}
Just a bit of explanation. In the for, we take each element of the list, and return lists composed of it followed by the permutation of all elements of the list except for the selected element.
For instance, if we take List(1,2,3), we'll compose lists formed by 1 and perm(List(2,3)), 2 and perm(List(1,3)) and 3 and perm(List(1,2)).
Since we are doing arbitrary-sized permutations, we keep track of how long each subpermutation can be. If a subpermutation is size 0, it is important we return a list containing an empty list. Notice that this is not an empty list! If we returned Nil in case 0, there would be no element for sl in the calling perm, and the whole "for" would yield Nil. This way, sl will be assigned Nil, and we'll compose a list el :: Nil, yielding List(el).
I was thinking about the original problem, though, and I'll post my solution here for reference. If you meant not having duplicated elements in the answer as a result of duplicated elements in the input, just add a removeDuplicates as shown below.
def comb[T](n: Int, l: List[T]): List[List[T]] =
n match {
case 0 => List(List())
case _ => for(i <- (0 to (l.size - n)).toList;
l1 = l.drop(i);
sl <- comb(n-1, l1.tail))
yield l1.head :: sl
}
It's a bit ugly, I know. I have to use toList to convert the range (returned by "to") into a List, so that "for" itself would return a List. I could do away with "l1", but I think this makes more clear what I'm doing. Since there is no filter here, modifying it to remove duplicates is much easier:
def comb[T](n: Int, l: List[T]): List[List[T]] = {
def comb1[T](n: Int, l: List[T]): List[List[T]] =
n match {
case 0 => List(List())
case _ => for(i <- (0 to (l.size - n)).toList;
l1 = l.drop(i);
sl <- comb(n-1, l1.tail))
yield l1.head :: sl
}
comb1(n, l).removeDuplicates
}
Daniel -- I'm not sure what Alex meant by duplicates, it may be that the following provides a more appropriate answer:
def perm[T](n: Int, l: List[T]): List[List[T]] =
n match {
case 0 => List(List())
case _ => for(el <- l.removeDuplicates;
sl <- perm(n-1, l.slice(0, l.findIndexOf {_ == el}) ++ l.slice(1 + l.findIndexOf {_ == el}, l.size)))
yield el :: sl
}
Run as
perm(2, List(1,2,2,2,1))
this gives:
List(List(2, 2), List(2, 1), List(1, 2), List(1, 1))
as opposed to:
List(
List(1, 2), List(1, 2), List(1, 2), List(2, 1),
List(2, 1), List(2, 1), List(2, 1), List(2, 1),
List(2, 1), List(1, 2), List(1, 2), List(1, 2)
)
The nastiness inside the nested perm call is removing a single 'el' from the list, I imagine there's a nicer way to do that but I can't think of one.
This solution was posted on Rosetta Code: http://rosettacode.org/wiki/Combinations_with_repetitions#Scala
def comb[A](as: List[A], k: Int): List[List[A]] =
(List.fill(k)(as)).flatten.combinations(k).toList
It is really not clear what you are asking for. It could be one of a few different things. First would be simple combinations of different elements in a list. Scala offers that with the combinations() method from collections. If elements are distinct, the behavior is exactly what you expect from classical definition of "combinations". For n-element combinations of p elements there will be p!/n!(p-n)! combinations in the output.
If there are repeated elements in the list, though, Scala will generate combinations with the item appearing more than once in the combinations. But just the different possible combinations, with the element possibly replicated as many times as they exist in the input. It generates only the set of possible combinations, so repeated elements, but not repeated combinations. I'm not sure if underlying it there is an iterator to an actual Set.
Now what you actually mean if I understand correctly is combinations from a given set of different p elements, where an element can appear repeatedly n times in the combination.
Well, coming back a little, to generate combinations when there are repeated elements in the input, and you wanna see the repeated combinations in the output, the way to go about it is just to generate it by "brute-force" using n nested loops. Notice that there is really nothing brute about it, it is just the natural number of combinations, really, which is O(p^n) for small n, and there is nothing you can do about it. You only should be careful to pick these values properly, like this:
val a = List(1,1,2,3,4)
def comb = for (i <- 0 until a.size - 1; j <- i+1 until a.size) yield (a(i), a(j))
resulting in
scala> comb
res55: scala.collection.immutable.IndexedSeq[(Int, Int)] = Vector((1,1), (1,2), (1,3), (1,4), (1,2), (1,3), (1,4), (2,3), (2,4), (3,4))
This generates the combinations from these repeated values in a, by first creating the intermediate combinations of 0 until a.size as (i, j)...
Now to create the "combinations with repetitions" you just have to change the indices like this:
val a = List('A','B','C')
def comb = for (i <- 0 until a.size; j <- i until a.size) yield (a(i), a(j))
will produce
List((A,A), (A,B), (A,C), (B,B), (B,C), (C,C))
But I'm not sure what's the best way to generalize this to larger combinations.
Now I close with what I was looking for when I found this post: a function to generate the combinations from an input that contains repeated elements, with intermediary indices generated by combinations(). It is nice that this method produces a list instead of a tuple, so that means we can actually solve the problem using a "map of a map", something I'm not sure anyone else has proposed here, but that is pretty nifty and will make your love for FP and Scala grow a bit more after you see it!
def comb[N](p:Seq[N], n:Int) = (0 until p.size).combinations(n) map { _ map p }
results in
scala> val a = List('A','A','B','C')
scala> comb(a, 2).toList
res60: List[scala.collection.immutable.IndexedSeq[Int]] = List(Vector(1, 1), Vector(1, 2), Vector(1, 3), Vector(1, 2), Vector(1, 3), Vector(2, 3))