Reputation:
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
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
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
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