Applying Multiple Filters on List - scala

Given these two functions:
scala> def maybe(x: Int): Boolean = x % 2 == 0
maybe: (x: Int)Boolean
scala> def good(x: Int): Boolean = x == 10
good: (x: Int)Boolean
Can I apply both good and maybe functions together?
scala> List(10) filter good filter maybe
res104: List[Int] = List(10)
scala> List(10) filter (good && maybe)
<console>:17: error: missing arguments for method good;
follow this method with `_' if you want to treat it as a partially applied function
List(10) filter (good && maybe)
^

You could evaluate them inside an anonymous function:
List(10) filter { x => good(x) && maybe(x) }
You can't really use andThen because composition is like the transitive property.
[(A => Boolean) && (A => Boolean)] != [(A => B) => C]
// ^ What you want ^ Composition

scala> def maybe(x: Int): Boolean = x % 2 == 0
maybe: (x: Int)Boolean
scala> def good(x: Int): Boolean = x % 3 == 0
good: (x: Int)Boolean
scala> (1 to 20) filter { i => List(good _, maybe _).forall(_(i)) }
res1: scala.collection.immutable.IndexedSeq[Int] = Vector(6, 12, 18)

Related

From a Set of Booleans, how to return Tuple containing number that are true, number that are false?

I'm pretty new of Scala, and I know there must be a nice way to do this, but I can't come up with something nice and readable.
I have a set of ids (strings), and for each id, I run some function that returns a boolean.
The result is a Set[Boolean], but I want to create a tuple containing two numbers, one is the number of true and one is the number of false.
What's a clean/readable way to do this?
Given your ids and f:
val ids: Set[String] = ???
def f(s: String): Boolean = ???
The following gets you there fairly concisely using the built-in partition function:
val (trues, falses) = ids partition f
(trues.size, falses.size)
You can utilize the count method of a Seq:
val ids: Seq[String] = Seq("1", "12", "3")
def containsOne(s: String) = s.contains('1')
val processedIds = ids.map(containsOne)
// first item is amount of trues, second is amount of falses
val count: (Int, Int) = (processedIds.count(identity), processedIds.count(_ == false))
You must use a Seq as a Set will 'flatten' out the collection of Boolean (to a maximum size of 2, no duplicates allowed).
Here's an expression that counts the number of even elements and odd elements in the set:
Set(3,4,5,6,8,3).toSeq.map{_ % 2 == 0}
.foldLeft((0,0)){(t,c) => if (c) (t._1+1, t._2) else (t._1, t._2+1)}
The toSeq is necessary to keep the output of map from being just a Set.
Just replace {_ % 2 == 0} with a call to your function.
Given your fn,
scala> def fn(x: String) = x.contains("customer")
fn: (x: String)Boolean
you have to .map to create boolean -> Set(Id), then aggregate by boolean, then count how many IDs for each boolean
scala> Set("customerId-1", "customerId-2", "id-3", "id-4")
.map(x => fn(x) -> x)
.groupBy(_._1)
.map { case (boolean, set) => boolean -> set.size }
res51: scala.collection.immutable.Map[Boolean,Int] = Map(false -> 2, true -> 2)
Here's my attempt at a one-liner (except that it doesn't fit on one line in this little box:(
My test function is true if division by 3 leaves a remainder of 1, and false otherwise, and I'm running it on the range 1 to 6 (i.e., 1,2,3,4,5):
scala> val x = (1 to 6).partition(_%3 == 1) match
| { case (s1,s2) => (s1.length, s2.length) }
x: (Int, Int) = (2,4)
And so, writing the main function in a little more generality,
scala> def boolCounter[T](
| s: Seq[T],
| f: T => Boolean): (Integer, Integer) =
| s.partition(f) match { case (s1, s2) => (s1.length, s2.length) }
boolCounter: [T](s: Seq[T], f: T => Boolean)(Integer, Integer)
scala> val r = 1 to 6
r: scala.collection.immutable.Range.Inclusive = Range 1 to 6
scala> val f: Int => Boolean = { x => x%3 == 1}
f: Int => Boolean = $$Lambda$1252/1891031939#5a090f62
scala> boolCounter(r, f)
res0: (Integer, Integer) = (2,4)

Drop a given number of positive items of a given list

Suppose I need a function List[Int] => Option[List[Int]] to drop exactly n elements of a given list if and only if all of them > 0. If the list size <= n the function should return None.
For instance:
def posn(n: Int): List[Int] => Option[List[Int]] = ???
val pos4: List[Int] => Option[List[Int]] = posn(4)
scala> pos4(Nil)
res18: Option[List[Int]] = None
scala> pos4(List(-1))
res19: Option[List[Int]] = None
scala> pos4(List(-1, 2, 3))
res20: Option[List[Int]] = None
scala> pos4(List(1, 2, 3))
res21: Option[List[Int]] = None
scala> pos4(List(1, 2, 3, 4, 5))
res22: Option[List[Int]] = Some(List(5))
scala> pos4(List(1, 2, 3, -4, 5))
res23: Option[List[Int]] = None
I am writing posn like that:
def posn(n: Int): List[Int] => Option[List[Int]] = xs =>
if (xs.size >= n && xs.take(n).forall(_ > 0)) Some(xs.drop(n)) else None
This function seems working bit it doesn't seem elegant and idiomatic. How would you re-write it ?
Here's an (arguably) more idiomatic implementation using Pattern Matching and a recursive call to posn - but I'm not sure it's preferable to your suggested implementation:
def posn(n: Int): List[Int] => Option[List[Int]] = xs => (n, xs) match {
case (0, _) => Some(xs) // stop if enough objects dropped
case (_, head :: tail) if head > 0 => posn(n - 1)(tail) // drop positive and move on
case _ => None // found a negative item or end of xs => "fail"
}
I don't know if there is an idiomatic or elegant way to do this. There seems to be no generic pattern that can be extracted from your logic, except what you have already done (using drop and take), so I don't believe you will find some more useful predefined method
However, you are traversing your list a few times, and this could be avoided:
def posn(n: Int): List[Int] => Option[List[Int]] = xs => {
val (head, tail) = xs.splitAt(n) //does take and drop in one run
if (head.lengthCompare(n) == 0 && head.forall(_ > 0)) Some(tail) // lengthCompare does not compute the whole length if there is no need to
else None
}
This is still not perfect, and more verbose than your version.
You could also do all of it at once, with tail recursion (here assuming n>=0):
def posn(n: Int): List[Int] => Option[List[Int]] = xs =>
if (n == 0) Some(xs)
else if (xs.isEmpty || xs.head <= 0) None
else posn(n - 1)(xs.tail)
This would be more efficient if List was naively implemented, but I really doubt you will see any improvement.
I would write a generic version and use that to define posn:
def dropWhen[T](n: Int, p: T => Boolean, l: List[T]): Option[List[T]] = {
val (f, s) = l.splitAt(n)
if (f.length >= n && f.forall(p)) { Some(s) } else { None }
}
def posn(n: Int): List[Int] => Option[List[Int]] = l => dropWhen(n, (i : Int) => i > 0, l)
Note this method scans the prefix of length n twice
Another (non-recursive) alternative: use zipWithIndex and dropWhile to drop the first N positive numbers, and then check head to see whether the first remaining item is exactly at position n: if it is, we got what we want, otherwise we can return None:
def posn(n: Int): List[Int] => Option[List[Int]] = xs =>
Some(xs.zipWithIndex.dropWhile { case (v, i) => v > 0 && i < n })
.find(_.headOption.exists(_._2 == n)) // first index should be n
.map(_.map(_._1)) // remove indices

Scala find an Int between a List of Int

I have an Int and I need to find in a List of Ints the upper and lower bounds for this Int.
For example:
In a List(1,3,6,9), when I ask for 2, I should get 1 and 3. Is there any pre-built function in the Scala collection API that I can use? I know that I can achieve this using the filter function, but I'm looking for an already existing API if any?
So, not built in, but here you go. Since you want return nothing for (e.g.) 0 and 10, we need to return an option.
var rs = List(1, 3, 6, 9) //> rs : List[Int] = List(1, 3, 6, 9)
def bracket(n: Int, rs: List[Int]) = {
val (l, r) = rs.span(_ < n)
if (l == Nil || r == Nil)
None
else if (r.head == n)
Some((n, n))
else
Some((l.last, r.head))
}
bracket(0, rs) //> res0: Option[(Int, Int)] = None
bracket(2, rs) //> res1: Option[(Int, Int)] = Some((1,3))
bracket(6, rs) //> res2: Option[(Int, Int)] = Some((6,6))
bracket(10, rs) //> res3: Option[(Int, Int)] = None
Alternative if you know the edge cases can't happen:
def bracket(n: Int, rs: List[Int]) = {
val (l, r) = rs.span(_ < n)
if (r.head == n)
(n, n)
else
(l.last, r.head)
}
bracket(2, rs) //> res0: (Int, Int) = (1,3)
bracket(6, rs) //> res1: (Int, Int) = (6,6)
(will throw an exception if there is no lower and upper bound for n)
If you can't have edge cases and you are OK with a tuple that is (<=, >) then simply
def bracket(n: Int, rs: List[Int]) = {
val (l, r) = rs.span(_ <= n)
(l.last, r.head)
}
bracket(2, rs) //> res0: (Int, Int) = (1,3)
bracket(6, rs) //> res1: (Int, Int) = (6,9)
You can use grouped or slide iterators to take 2 elements at a time and test condition:
// you can also add 'numbers.sorted' if your list is not sorted
def findBoundries(x: Int, numbers: List[Int]): Option[List[Int]] =
numbers.grouped(2).find {
case a :: b :: Nil => a <= x && x <= b
}
findBoundries(2,List(1,3,6,9))
You can, as a workaround, also convert your List to a NavigableSet (Java class that has higher and lower methods, which do more or less what you require).

Convert iterative two sum k to functional

I have this code in Python that finds all pairs of numbers in an array that sum to k:
def two_sum_k(array, k):
seen = set()
out = set()
for v in array:
if k - v in seen:
out.add((min(v, k-v), max(v, k-v)))
seen.add(v)
return out
Can anyone help me convert this to Scala (in a functional style)? Also with linear complexity.
I think this is a classic case of when a for-comprehension can provide additional clarity
scala> def algo(xs: IndexedSeq[Int], target: Int) =
| for {
| i <- 0 until xs.length
| j <- (i + 1) until xs.length if xs(i) + xs(j) == target
| }
| yield xs(i) -> xs(j)
algo: (xs: IndexedSeq[Int], target: Int)scala.collection.immutable.IndexedSeq[(Int, Int)]
Using it:
scala> algo(1 to 20, 15)
res0: scala.collection.immutable.IndexedSeq[(Int, Int)] = Vector((1,14), (2,13), (3,12), (4,11), (5,10), (6,9), (7,8))
I think it also doesn't suffer from the problems that your algorithm has
I'm not sure this is the clearest, but folds usually do the trick:
def two_sum_k(xs: Seq[Int], k: Int) = {
xs.foldLeft((Set[Int](),Set[(Int,Int)]())){ case ((seen,out),v) =>
(seen+v, if (seen contains k-v) out+((v min k-v, v max k-v)) else out)
}._2
}
You could just filter for (k-x <= x) by only using those x as first element, which aren't bigger than k/2:
def two_sum_k (xs: List[Int], k: Int): List [(Int, Int)] =
xs.filter (x => (x <= k/2)).
filter (x => (xs contains k-x) && (xs.indexOf (x) != xs.lastIndexOf (x))).
map (x => (x, k-x)).distinct
My first filter on line 3 was just filter (x => xs contains k-x)., which failed as found in the comment by Someone Else. Now it's more complicated and doesn't find (4, 4).
scala> li
res6: List[Int] = List(2, 3, 3, 4, 5, 5)
scala> two_sum_k (li, 8)
res7: List[(Int, Int)] = List((3,5))
def twoSumK(xs: List[Int], k: Int): List[(Int, Int)] = {
val tuples = xs.iterator map { x => (x, k-x) }
val potentialValues = tuples map { case (a, b) => (a min b) -> (a max b) }
val values = potentialValues filter { xs contains _._2 }
values.toSet.toList
}
Well, a direct translation would be this:
import scala.collection.mutable
def twoSumK[T : Numeric](array: Array[T], k: T) = {
val num = implicitly[Numeric[T]]
import num._
val seen = mutable.HashSet[T]()
val out: mutable.Set[(T, T)] = mutable.HashSet[(T, T)]()
for (v <- array) {
if (seen contains k - v) out += min(v, k - v) -> max(v, k - v)
seen += v
}
out
}
One clever way of doing it would be this:
def twoSumK[T : Numeric](array: Array[T], k: T) = {
val num = implicitly[Numeric[T]]
import num._
// One can write all the rest as a one-liner
val s1 = array.toSet
val s2 = s1 map (k -)
val s3 = s1 intersect s2
s3 map (v => min(v, k - v) -> max(v, k - v))
}
This does the trick:
def two_sum_k(xs: List[Int], k: Int): List[(Int, Int)] ={
xs.map(a=>xs.map(b=>(b,a+b)).filter(_._2 == k).map(b=>(b._1,a))).flatten.collect{case (a,b)=>if(a>b){(b,a)}else{(a,b)}}.distinct
}

Scala: Defining a function to be the correct type

I've been playing around with Scala code and have come up against a compiler error which I don't understand. The code generates a vector of pairs of Ints and then tries to filter it.
val L = for (x <- (1 to 5)) yield (x, x * x)
val f = (x: Int, y: Int) => x > 3
println(L.filter(f))
The compiler complains about trying to use f as an argument for the filter method with the compiler error message being:
error: type mismatch;
found : (Int, Int) => Boolean
required: ((Int, Int)) => Boolean
How do I define the function f correctly to satisfy the required function type? I tried to add extra parentheses around (x: Int, y: Int) but this gave:
error: not a legal formal parameter
val f = ((x: Int, y: Int)) => x > 3
^
f has type Function2[Int, Int, Boolean]. L's type is IndexedSeq[Tuple2[Int, Int]] and so filter expects a function of type Function1[Tuple2[Int, Int], Boolean]. Every FunctionN[A, B, .., R] trait has a method tupled, which returns a function of type Function1[TupleN[A, B, ..], R]. You can use it here to transform f to the type expected by L.filter.
println(L.filter(f.tupled))
> Vector((4,16), (5,25))
Alternatively you can redefine f to be a Function1[Tuple2[Int, Int], Boolean] as follows and use it directly.
val f = (t: (Int, Int)) => t._1 > 3
println(L.filter(f))
> Vector((4,16), (5,25))
val f = (xy: (Int, Int)) => xy._1 > 3
println (L.filter (f))
If you do
val f = (x: Int, y: Int) => x > 3
you define a function which takes two ints, which is not the same as a function which takes a pair of ints as parameter.
Compare:
scala> val f = (x: Int, y: Int) => x > 3
f: (Int, Int) => Boolean = <function2>
scala> val f = (xy: (Int, Int)) => xy._1 > 3
f: ((Int, Int)) => Boolean = <function1>
If you don't want to rewrite your function to explicitely useing Tuple2 (as suggested by missingfaktor and user unknown), you can define a implicit method to do it automatically. This lets the function f untouched (you aren't forced to always call it with a Tuple2 parameter) and easier to understand, because you still use the identifiers x and y.
implicit def fun2ToTuple[A,B,Res](f:(A,B)=>Res):((A,B))=>Res =
(t:(A,B)) => f(t._1, t._2)
val L = for (x <- (1 to 5)) yield (x, x * x)
val f = (x: Int, y: Int) => x > 3
val g = (x: Int, y: Int) => x % 2 > y % 3
L.filter(f) //> Vector((4,16), (5,25))
L.filter(g) //> Vector((3,9))
f(0,1) //> false
f((4,2)) //> true
Now every Function2 can also be used as a Function1 with an Tuple2 as parameter, because it uses the implicit method to convert the function if needed.
For functions with more than two parameters the implicit defs looks similiar:
implicit def fun3ToTuple[A,B,C,Res](f:(A,B,C)=>Res):((A,B,C))=>Res =
(t:(A,B,C)) => f(t._1, t._2, t._3)
implicit def fun4ToTuple[A,B,C,D,Res](f:(A,B,C,D)=>Res):((A,B,C,D))=>Res =
(t:(A,B,C,D)) => f(t._1, t._2, t._3, t._4)
...