user8103380
user8103380

Reputation:

Scala takeWhile Method with foldLeft and foldRight

I need to make takeWhile() using foldLeft() and foldRight(). I've come up with this:

def takeWhile(ls:List[Int], p:Int => Boolean): List[Int] = {
    ls.foldLeft(List[Int]())(a,z) =>
    if (p(z)) z :: a
    else a)
}

def takeWhile(ls:List[Int], p:Int => Boolean): List[Int] = {
    ls.foldRight(List[Int]())(a,z) =>
    if (p(a)) a :: z
    else z)
}

But with foldLeft when I call

takeWhile(List(1,2,3,4,5), _< 3)
takeWhile(List(1,2,3,4,5), _> 4)
takeWhile(List(5,6,7,1,2,5), _> 4)

It returns

List(2,1)
List(5)
List(5,7,6,5)

With foldRight I get

List(5)
List(5,6,7,5)

But it should be

List(1,2)
List()
List(5,6,7)

How do I make it stop when condition is not met?

Upvotes: 2

Views: 1040

Answers (3)

Cyrille Corpet
Cyrille Corpet

Reputation: 5305

Here's one using foldRight (since you asked for both):

def takeWhile[T](list: List[T], p: T => Boolean) =
  list.foldRight(List.empty[T]){
    case (t, l) if p(t) => t :: l
    case (t, l) => Nil
  }

It reinitialize the state to Nil whenever it finds a value that should not be taken.

Upvotes: 0

Thomas B&#246;hm
Thomas B&#246;hm

Reputation: 1486

One way to do is the following (pretty much the same as you did it):

def takeWhile(ls:List[Int], p:Int => Boolean): List[Int] = {
    ls.foldLeft(List[Int]()){
      case (a,z) =>
      if (p(z)) z :: a
      else return a.reverse
    }
}

It prints the following:

List(1, 2)
List()
List(5, 6, 7)

The return Returns from the takeWhile-method, so it does what you want, because it stops the foldLeft-operation.

Sorry I modified your Code (other brackets etc), but it didn't compile when copying.

Upvotes: 2

sheunis
sheunis

Reputation: 1544

Here is one way to get foldLeft() to work. It's hacky, but it gets the job done and it's a starting point:

def takeWhile(ls:List[Int], p:Int => Boolean): List[Int] = {
  ls.foldLeft((List[Int](), true)) {
    (a, z) =>
      if (a._2 && p(z)) (z :: a._1, a._2)
      else (a._1, false)
  }._1.reverse
}

Upvotes: 1

Related Questions