joesan
joesan

Reputation: 15435

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?

Upvotes: 1

Views: 394

Answers (3)

Danny Mor
Danny Mor

Reputation: 1273

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))

Upvotes: 1

The Archetypal Paul
The Archetypal Paul

Reputation: 41769

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)

Upvotes: 2

Ashalynd
Ashalynd

Reputation: 12573

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).

Upvotes: 0

Related Questions