Implementing `elem` with foldLeft - scala

I'm working on Learn You a Haskell. On the "fold" section, I need to implement elem (given an element, find out if it's in the list - True or False).
def myElem(a: Char, as: List[Char]): Boolean = as match {
case Nil => false
case x::Nil => println(x); if(x == a) true else false
case x::_ => println(x); as.foldLeft(false){ (_, elem) =>
if(a == elem) true
else myElem(a, as.tail)
}
}
However, it's failing on a simple example:
scala> myElem('a', "ab".toList)
a
b
res8: Boolean = false
What am I doing wrong here? Also, as extra, I'd appreciate any suggestion on improvement of this code.
As an aside, I would think a find would be more appropriate here.

This is a pretty simple implementation:
def elem[A](a: A, as: List[A]): Boolean = as match {
case Nil => false
case h :: t => (h == a) || elem(a, t)
}
Also, instead of find you could use exists:
def elem[A](a: A, as: List[A]) = as.exists(_ == a)
If you want to foldLeft you can, but you'll still traverse the whole list instead of stopping early:
def elem[A](a: A, as: List[A]) =
as.foldLeft(false)((bool, value) => bool || value == a)

Related

Scala - recursive compare function

I'm working on a function to recursively run through a list of Ints and return a Boolean stating whether each item in the list is the same number. I've taken a stab at it below but it's not passing the tests I'm running. Here's what I've got, any suggestions are much appreciated. Thanks!
def equalList (xs : List[Int]) : Boolean = {
def equalAux (xs:List[Int], value:Int) : Boolean = {
xs match {
case Nil => true
case x :: xs if (x == value) => equalAux(xs, x)
case x :: xs if (x != value) => false
}
}
equalAux(xs, x)
}
As you said in your comment, you just need to make sure the list is not empty so you can give an initial value to your recursive function:
def equalList(xs: List[Int]): Boolean = {
def equalAux (xs: List[Int], value: Int): Boolean = {
xs match {
case Nil => true
case x :: xs if x == value => equalAux(xs, x)
case x :: _ if x != value => false
}
}
// Check to make sure the list has at least one item initially
xs match {
case Nil => true
case head :: tail => equalAux(tail, head)
}
}
println(equalList(List.empty)) // true
println(equalList(List(1))) // true
println(equalList(List(1, 1, 1, 1))) // true
println(equalList(List(1, 1, 1, 1, 2))) // false
println(equalList(List(1, 2, 1))) // false
Do you need a recursive function? If not, I would use Set as a trick:
myList.toSet.size <= 1 // because empty list returns true. Else make it == 1
If you do need recursion, then #Tyler answer is the answer I would also give.

How to implement maxBy with multiple max in Scala

I need a maxBy that returns all max values in case of equality.
Here is the signature and a first implementation :
def maxBy[A, B](as: Seq[A])(f: A => B)(implicit cmp: Ordering[B]) : Seq[A] =
as.groupBy(f).toList.maxBy(_._1)._2
Example :
maxBy(Seq(("a", "a1"),("a", "a2"),("b", "b1"),("b", "b2")))(_._1)
res6: Seq[(String, String)] = List(("b", "b1"), ("b", "b2"))
Updated with #thearchetypepaul comment
def maxBy[A, B](l: Seq[A])(f: A => B)(implicit cmp: Ordering[B]) : Seq[A] = {
l.foldLeft(Seq.empty[A])((b, a) =>
b.headOption match {
case None => Seq(a)
case Some(v) => cmp.compare(f(a), f(v)) match {
case -1 => b
case 0 => b.+:(a)
case 1 => Seq(a)
}
}
)
}
Is there a better way ?
(1) Ordering#compare promises to denote the three possible results by a negative, positive, or zero number, not -1, 1, or 0 necessarily.
(2) Option#fold is generally (though not universally) considered to be more idiomatic than pattern matching.
(3) You are calling f possibly multiple times per element. TraversableOnce#maxBy used to do this before it was fixed in 2.11.
(4) You only accept Seq. The Scala library works hard to use CanBuildFrom to generalize the algorithms; you might want to as well.
(5) You can use the syntactic sugar B : Ordering if you would like.
(6) You prepend to the Seq. This is faster than appending, since prepending is O(1) for List and appending is O(n). But you wind up with the results in reverse order. foldRight will correct this. (Or you can call reverse on the final result.)
If you want to allow the use of CanBuildFrom,
def maxBy[A, Repr, That, B : Ordering](elements: TraversableLike[A, Repr])(f: A => B)(implicit bf: CanBuildFrom[Repr, A, That]): That = {
val b = bf()
elements.foldLeft(Option.empty[B]) { (best, element) =>
val current = f(element)
val result = best.fold(0)(implicitly[Ordering[B]].compare(current, _))
if (result > 0) {
b.clear()
}
if (result >= 0) {
b += element
Some(current)
} else {
best
}
}
b.result
}
If you want to work with TraversableOnce,
def maxBy[A, B : Ordering](elements: TraversableOnce[A])(f: A => B): Seq[A] = {
elements.foldRight((Option.empty[B], List.empty[A])) { case (element, (best, elements)) =>
val current = f(element)
val result = best.fold(0)(implicitly[Ordering[B]].compare(current, _))
if (result > 0) {
(Some(current), List(element))
} else {
(best, if (result == 0) element +: elements else elements)
}
}._2
}
if the dataset is small the performance shouldn't concern you that much
and you can just sort, reverse, and takeWhile.
def maxBy[A,B:Ordering](l:List[A], f: A => B): List[A] = {
l.sortBy(f).reverse match {
case Nil => Nil
case h :: t => h :: t.takeWhile(x => f(x) == f(h))
}
}
where the f should be an isomorphism on A.
and you can also save f(h) before comparison

how to check whether given List[Int] is sorted in scala?

I would like to know whether is there any isSorted() function exist or not in scala.
Question: check whether List[Int] is sorted or not, If not remove smallest number and do again till List[Int] become sorted?
I want only 1 or 2 line program.
You can compare each pair in the input sequence for lists containing more than 1 item:
def isSorted[T](s: Seq[T])(implicit ord: Ordering[T]): Boolean = s match {
case Seq() => true
case Seq(_) => true
case _ => s.sliding(2).forall { case Seq(x, y) => ord.lteq(x, y) }
}
It's not the best solution but you can use sorted method on list and then compare it with original one;
def sorted(l: List[Int]): Boolean = l == l.sorted
With some lazyness:
def isSorted(l:List[Int]):Boolean = {
val list = l.view
!list.zip(list.tail).exists {case (x,y) => x>y}
}
Performing a sort just to check if the list is already sorted is a bit of an overkill. The optimal solution here seems to be the most obvious one, which is just describing the problem in human language and transferring it into code:
def isSorted[T](list: List[T])(implicit ord: Ordering[T]): Boolean = list match {
case Nil => true // an empty list is sorted
case x :: Nil => true // a single-element list is sorted
case x :: xs => ord.lteq(x, xs.head) && isSorted(xs) // if the first two elements are ordered and the rest are sorted, the full list is sorted too
}
If you want it shorter, you could trade the 2nd case for a bit of readability:
def isSorted[T](list: List[T])(implicit ord: Ordering[T]): Boolean = list match {
case Nil => true
case x :: xs => xs.headOption.fold(true)(ord.lteq(x, _)) && isSorted(xs)
}
If you want a one-liner, that would be not readable at all:
def isSorted[T](list: List[T])(implicit ord: Ordering[T]): Boolean = list.headOption.fold(true)(a => list.tail.headOption.fold(true)(ord.lteq(a, _) && isSorted(list.tail.tail)))
def isSorted(xs: List[Int]): Boolean = (xs.tail zip xs).forall(pair => pair._1 - pair._2 > 0)
Using `zip`
Lets do it without actually sorting the list.
Drop the head element in the intermediate list and then compare in pairs with original list. This way, ith element compares with i+1th element of the original list.
scala> val originalList = List(10, 20, 30, 40)
val originalList: List[Int] = List(10, 20, 30, 40)
scala> val intermediate = originalList.drop(1)
val intermediate: List[Int] = List(20, 30, 40)
scala> originalList.zip(intermediate)
val res5: List[(Int, Int)] = List((10,20), (20,30), (30,40))
scala> originalList.zip(intermediate).forall { case (orig, in) => orig <= in }
val res17: Boolean = true
A inefficient but easy to understand answer:
def specialSort(a: List[Int]): List[Int] =
if (a == a.sorted) a
else specialSort(a.filterNot(_ == a.min))
l == l.sorted didn't work for me, managed to do it with l sameElements l.sorted
Here your one-line homework solution
def removeMinWhileNotSorted[A: Ordering](xs: List[A]): List[A] = if (xs == xs.sorted) xs else xs.splitAt(xs.indexOf(xs.min)) match {case (prefix, m :: postfix) => removeMinWhileNotSorted(prefix ++ postfix)}
It does not exists. But it is easy to do: create a list with the joined version of the list and the same list sorted as you want and verify both elements of the joined list are the same.
Something like this:
import org.junit.Assert._
val sortedList = List(1, 3, 5, 7)
val unsortedList = List(10, 1, 8, 3, 5, 5, 2, 9)
// detailed test. It passes.
sortedList
.zip(sortedList.sortWith((a,b) => a.compareTo(b) < 0)) // this is the required sorting criteria.
.foreach(x => assertEquals("collection is not sorted", x._1, x._2))
// easier to read but similar test. It fails.
unsortedList
.zip(unsortedList.sorted) // this is the required sorting criteria.
.foreach(x => assertEquals("collection is not sorted", x._1, x._2))
a function could be:
def isSorted(list: List[Int]): Boolean = !list.zip(list.sortWith((a, b) => a.compareTo(b) < 0)).exists(p => !p._1.equals(p._2))
def isSorted[T <% Ordered[T]](list: List[T]): Boolean =
list.sliding(2).forall(p => (p.size==1) || p(0) < p(1))
I assumed that if two neighbor elements are equal it is legal too.
def isSorted[T <% Ordered[T]](l: List[T]):Boolean ={
val a = l.toArray
(1 until a.length).forall(i => a(i-1) <= a(i))
}
Another possibility (not necessarily any better than some of the other suggestions)
def isSorted[T <% Ordered[T]](a: List[T]): Boolean =
if (a == Nil) true // an empty list is sorted
else a.foldLeft((true, a.head))(
(prev, v1) => {
val (p, v0) = prev
(p && v0 <= v1, v1)
})._1
Results for a few test cases:
isSorted(Nil) -> true
isSorted(1 :: Nil) -> true
isSorted(2 :: 3 :: Nil) -> true
isSorted(1 :: 2 :: 5 :: 8 :: Nil) -> true
isSorted(1 :: 1 :: 2 :: 2 :: Nil) -> true
isSorted(3 :: 2 :: Nil) -> false
isSorted(1 :: 2 :: 3 :: 1 :: Nil) -> false
You can use tail recursion to less create objects and to avoid stack overflow for long lists. This version is lazy, function return value instantly after a first unordered pair.
#scala.annotation.tailrec
def isSorted[T : Ordering](values: List[T]): Boolean = {
import scala.math.Ordering.Implicits._
values match {
case fst :: snd :: _ if fst <= snd => isSorted(values.tail)
case _ :: _ :: _ => false
case _ => true
}
}
This works.
def check(list: List[Int]) = {
#tailrec
def isSorted(list: List[Int], no: Int, acc: Boolean): Boolean = {
if (list.tail == Nil) acc
else if (list.head > no) {
isSorted(list.tail, list.head, acc = true)
}
else isSorted(list.tail, list.head, acc=false)
}
isSorted(list, Integer.MIN_VALUE, acc = false)
}

Whats wrong with this scala tuple?

Trying to create a method that determines if a set is a subset of another set, both given as parameters. When I tried to test it the console printed out
scala.MatchError : (List(1, 2, 3, 4, 5, 6, 7),List(1, 2, 3, 4)) (of class scala.Tuple2),
the two lists given are what I was using as parameters to test it. Also, scala was making me type out return in front of true and false, any ideas what led to this either?
def subset(a: List[Int], b: List[Int]): Boolean ={
(a,b) match {
case (_,Nil)=> return true
}
b match {
case h::t if (a.contains(h)) => subset(a,t)
case h::t => return false
}}
The other answers don't really answer exactly why your code is incorrect. It appears that you're handling the case when list b is empty and non-empty and that everything should be okay, but in fact you're actually not. Let's look at your code again, with some formatting fixes.
def subset(a: List[Int], b: List[Int]): Boolean = {
(a, b) match {
case (_, Nil) => return true
} // we can never make it past here, because either we return true,
// or a MatchError is raised.
b match {
case h :: t if (a.contains(h)) => subset(a,t)
case h :: t => return false
}
}
The real problem here is that you have two completely disconnected match statements. So when b is non-empty, the first match will fail, because it only handles the case when b is Nil.
As pointed out in the other solutions, the proper way to do this is to merge the two match statements together into one.
def subset(a: List[Int], b: List[Int]): Boolean = {
(a, b) match {
case (_, Nil) => true
case (xs, head :: tail) if(xs contains head) => subset(xs, tail)
case _ => false
}
}
Notice how the return statements are no longer needed. In scala you should avoid using return as much as possible, as it's likely that your way of thinking around return actually lead you into this trap. Methods that return early are likely to lead to bugs, and are difficult to read.
A cleaner way to implement this could use diff. b can be considered a subset of a if the set of elements of b minus the elements of a is empty.
def subset(a: List[Int], b: List[Int]): Boolean = (b.distinct diff a.distinct).nonEmpty
distinct is only required if it's possible for a and b to contain duplicates, because we're trying a List like a Set when it's actually not.
Better yet, if we convert the Lists to Sets, then we can use subsetOf.
def subset(a: List[Int], b: List[Int]): Boolean = b.toSet.subsetOf(a.toSet)
Scala match expression should match to at least one case expression. Otherwise the MatchError is raised.
You should have used the following cases:
(a, b) match {
case (_, Nil) => true
case (aa, h :: t) if aa contains h => subset(aa, t)
case _ => false
}
An alternative way could be to call methods in standard library.
For each element in 'b', check if 'a' contains that element.
Here is the simple code:
def subset(a: List[Int], b: List[Int]): Boolean = {
(b.forall(a.contains(_)))
}
MatchError - This class implements errors which are thrown whenever an object doesn't match any pattern of a pattern matching expression.
Obviously the second list having elements in it will cause this error, as no pattern will match. You should just add another branch to the first match like so:
def subset(a: List[Int], b: List[Int]): Boolean = {
(a, b) match {
case (_, List()) => return true
case _ => b match {
case h :: t if (a.contains(h)) => subset(a, t)
case h :: t => return false
}
}
}
MatchError occurs whenever an object doesn't match any pattern of a pattern matching expression.
An alternative way is by using dropWhile or takeWhile
def subsets(a:List[Int], b:List[Int]):Boolean = {
return b.dropWhile { ele => a.contains(ele)}.size==0
}
OR
def subsets(a:List[Int], b:List[Int]):Boolean = {
return b.takeWhile { ele => a.contains(ele)}.size==b.size
}

Idiomatic construction to check whether a collection is ordered

With the intention of learning and further to this question, I've remained curious of the idiomatic alternatives to explicit recursion for an algorithm that checks whether a list (or collection) is ordered. (I'm keeping things simple here by using an operator to compare and Int as type; I'd like to look at the algorithm before delving into the generics of it)
The basic recursive version would be (by #Luigi Plinge):
def isOrdered(l:List[Int]): Boolean = l match {
case Nil => true
case x :: Nil => true
case x :: xs => x <= xs.head && isOrdered(xs)
}
A poor performing idiomatic way would be:
def isOrdered(l: List[Int]) = l == l.sorted
An alternative algorithm using fold:
def isOrdered(l: List[Int]) =
l.foldLeft((true, None:Option[Int]))((x,y) =>
(x._1 && x._2.map(_ <= y).getOrElse(true), Some(y)))._1
It has the drawback that it will compare for all n elements of the list even if it could stop earlier after finding the first out-of-order element. Is there a way to "stop" fold and therefore making this a better solution?
Any other (elegant) alternatives?
This will exit after the first element that is out of order. It should thus perform well, but I haven't tested that. It's also a lot more elegant in my opinion. :)
def sorted(l:List[Int]) = l.view.zip(l.tail).forall(x => x._1 <= x._2)
By "idiomatic", I assume you're talking about McBride and Paterson's "Idioms" in their paper Applicative Programming With Effects. :o)
Here's how you would use their idioms to check if a collection is ordered:
import scalaz._
import Scalaz._
case class Lte[A](v: A, b: Boolean)
implicit def lteSemigroup[A:Order] = new Semigroup[Lte[A]] {
def append(a1: Lte[A], a2: => Lte[A]) = {
lazy val b = a1.v lte a2.v
Lte(if (!a1.b || b) a1.v else a2.v, a1.b && b && a2.b)
}
}
def isOrdered[T[_]:Traverse, A:Order](ta: T[A]) =
ta.foldMapDefault(x => some(Lte(x, true))).fold(_.b, true)
Here's how this works:
Any data structure T[A] where there exists an implementation of Traverse[T], can be traversed with an Applicative functor, or "idiom", or "strong lax monoidal functor". It just so happens that every Monoid induces such an idiom for free (see section 4 of the paper).
A monoid is just an associative binary operation over some type, and an identity element for that operation. I'm defining a Semigroup[Lte[A]] (a semigroup is the same as a monoid, except without the identity element) whose associative operation tracks the lesser of two values and whether the left value is less than the right value. And of course Option[Lte[A]] is just the monoid generated freely by our semigroup.
Finally, foldMapDefault traverses the collection type T in the idiom induced by the monoid. The result b will contain true if each value was less than all the following ones (meaning the collection was ordered), or None if the T had no elements. Since an empty T is sorted by convention, we pass true as the second argument to the final fold of the Option.
As a bonus, this works for all traversable collections. A demo:
scala> val b = isOrdered(List(1,3,5,7,123))
b: Boolean = true
scala> val b = isOrdered(Seq(5,7,2,3,6))
b: Boolean = false
scala> val b = isOrdered(Map((2 -> 22, 33 -> 3)))
b: Boolean = true
scala> val b = isOrdered(some("hello"))
b: Boolean = true
A test:
import org.scalacheck._
scala> val p = forAll((xs: List[Int]) => (xs /== xs.sorted) ==> !isOrdered(xs))
p:org.scalacheck.Prop = Prop
scala> val q = forAll((xs: List[Int]) => isOrdered(xs.sorted))
q: org.scalacheck.Prop = Prop
scala> p && q check
+ OK, passed 100 tests.
And that's how you do idiomatic traversal to detect if a collection is ordered.
I'm going with this, which is pretty similar to Kim Stebel's, as a matter of fact.
def isOrdered(list: List[Int]): Boolean = (
list
sliding 2
map {
case List(a, b) => () => a < b
}
forall (_())
)
In case you missed missingfaktor's elegant solution in the comments above:
Scala < 2.13.0
(l, l.tail).zipped.forall(_ <= _)
Scala 2.13.x+
l.lazyZip(l.tail).forall(_ <= _)
This solution is very readable and will exit on the first out-of-order element.
The recursive version is fine, but limited to List (with limited changes, it would work well on LinearSeq).
If it was implemented in the standard library (would make sense) it would probably be done in IterableLike and have a completely imperative implementation (see for instance method find)
You can interrupt the foldLeft with a return (in which case you need only the previous element and not boolean all along)
import Ordering.Implicits._
def isOrdered[A: Ordering](seq: Seq[A]): Boolean = {
if (!seq.isEmpty)
seq.tail.foldLeft(seq.head){(previous, current) =>
if (previous > current) return false; current
}
true
}
but I don't see how it is any better or even idiomatic than an imperative implementation. I'm not sure I would not call it imperative actually.
Another solution could be
def isOrdered[A: Ordering](seq: Seq[A]): Boolean =
! seq.sliding(2).exists{s => s.length == 2 && s(0) > s(1)}
Rather concise, and maybe that could be called idiomatic, I'm not sure. But I think it is not too clear. Moreover, all of those methods would probably perform much worse than the imperative or tail recursive version, and I do not think they have any added clarity that would buy that.
Also you should have a look at this question.
To stop iteration, you can use Iteratee:
import scalaz._
import Scalaz._
import IterV._
import math.Ordering
import Ordering.Implicits._
implicit val ListEnumerator = new Enumerator[List] {
def apply[E, A](e: List[E], i: IterV[E, A]): IterV[E, A] = e match {
case List() => i
case x :: xs => i.fold(done = (_, _) => i,
cont = k => apply(xs, k(El(x))))
}
}
def sorted[E: Ordering] : IterV[E, Boolean] = {
def step(is: Boolean, e: E)(s: Input[E]): IterV[E, Boolean] =
s(el = e2 => if (is && e < e2)
Cont(step(is, e2))
else
Done(false, EOF[E]),
empty = Cont(step(is, e)),
eof = Done(is, EOF[E]))
def first(s: Input[E]): IterV[E, Boolean] =
s(el = e1 => Cont(step(true, e1)),
empty = Cont(first),
eof = Done(true, EOF[E]))
Cont(first)
}
scala> val s = sorted[Int]
s: scalaz.IterV[Int,Boolean] = scalaz.IterV$Cont$$anon$2#5e9132b3
scala> s(List(1,2,3)).run
res11: Boolean = true
scala> s(List(1,2,3,0)).run
res12: Boolean = false
If you split the List into two parts, and check whether the last of the first part is lower than the first of the second part. If so, you could check in parallel for both parts. Here the schematic idea, first without parallel:
def isOrdered (l: List [Int]): Boolean = l.size/2 match {
case 0 => true
case m => {
val low = l.take (m)
val high = l.drop (m)
low.last <= high.head && isOrdered (low) && isOrdered (high)
}
}
And now with parallel, and using splitAt instead of take/drop:
def isOrdered (l: List[Int]): Boolean = l.size/2 match {
case 0 => true
case m => {
val (low, high) = l.splitAt (m)
low.last <= high.head && ! List (low, high).par.exists (x => isOrdered (x) == false)
}
}
def isSorted[A <: Ordered[A]](sequence: List[A]): Boolean = {
sequence match {
case Nil => true
case x::Nil => true
case x::y::rest => (x < y) && isSorted(y::rest)
}
}
Explain how it works.
my solution combine with missingfaktor's solution and Ordering
def isSorted[T](l: Seq[T])(implicit ord: Ordering[T]) = (l, l.tail).zipped.forall(ord.lt(_, _))
and you can use your own comparison method. E.g.
isSorted(dataList)(Ordering.by[Post, Date](_.lastUpdateTime))