I have an exercise to check if two adjoined elements are ordered using sliding,map,reduceLeft. For example:
val seq1 = Seq(1,2,2,4)
isOrdered(seq1)(_ < _) == false
isOrdered(seq1)(_ <= _) == true
def isOrdered[A](seq: Seq[A])(leq: (A,A) => Boolean): Boolean = {
}
honestly I don't know what to start with.
"using sliding,map,reduce"
def isOrdered[A](seq: Seq[A])(pred: (A,A) => Boolean): Boolean =
seq.sliding(2)
.map{case Seq(a,b) => pred(a,b)}
.reduce(_ && _)
Note: Not safe for sequences smaller than 2 elements.
Here's how you can do it using those three operations:
def isOrdered[A](seq: Seq[A])(leq: (A, A) => Boolean): Boolean =
seq
.sliding(2)
.map { case e1 :: e2 :: Nil => leq(e1, e2) }
.reduceLeft(_ && _)
First we divide the sequence into groups of two consecutive elements using sliding. Then we apply leq on each pair (in other words, we map each two-element list into result of leq on those two elements). Lastly, we reduce the result sequence of Booleans into a single Boolean with a logical AND, meaning that our predicate needs to hold for all values.
val seq1 = Seq(1, 2, 2, 4)
val less: (Int, Int) => Boolean = _ < _
val lessOrEqual: (Int, Int) => Boolean = _ <= _
isOrdered(seq1)(less) // false
isOrdered(seq1)(lessOrEqual) // true
There are some unsafety concerns here:
If you have a one-element sequence, the sliding operation will produce an iterator over a single-list element, and the pattern matching will fail.
If you have an empty sequence, reduce will explode.
One approach includes forall, where leq: (A,A) => Boolean must hold for each and every element,
def isOrdered[A](seq: Seq[A])(leq: (A,A) => Boolean): Boolean = {
seq.sliding(2).forall { case(Seq(l,r)) => leq(l,r) }
}
Thus for val seq1 = Seq(1,2,2,4),
scala> isOrdered(seq1)(_<_)
val res5: Boolean = false
scala> isOrdered(seq1)(_<=_)
val res6: Boolean = true
Related
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)
}
I have a code such as:
val strs = List("hello", "andorra", "trab", "world")
def f1(s: String) = !s.startsWith("a")
def f2(s: String) = !s.endsWith("b")
val result = strs.filter(f1).filter(f2)
now, f1 and f2 should be applied based on a condition, such as:
val tmp1 = if (cond1) strs.filter(f1) else strs
val out = if (cond2) tmp1.filter(f2) else tmp1
is there a nicer way to do this, without using a temporary variable tmp1?
one way would to filter based on a list of functions, such as:
val fs = List(f1 _,f2 _)
fs.foldLeft(strs)((fn, list) => list.filter(fn))
but then I would need to build a list of functions based on the conditions (and so, I would move the problem of using a temporary string list variable, to using a temporary function list variable (or I should need to use a mutable list)).
I am looking something like this (of course this does not compile, otherwise I would already have the answer to the question):
val result =
strs
.if(cond1, filter(f1))
.if(cond2, filter(f2))
You could use an implicit class to give you this syntax:
val strs = List("hello", "andorra", "trab", "world")
def f1(s: String) = !s.startsWith("a")
def f2(s: String) = !s.endsWith("b")
val cond1 = true
val cond2 = true
implicit class FilterHelper[A](l: List[A]) {
def ifFilter(cond: Boolean, f: A => Boolean) = {
if (cond) l.filter(f) else l
}
}
strs
.ifFilter(cond1, f1)
.ifFilter(cond2, f2)
res1: List[String] = List(hello, world)
I would have used if as the method name but it's a reserved word.
You can do this by summing your predicate functions.
Observe that a filter predicate, A => Boolean, has an append operation:
def append[A](p1: A => Boolean, p2: A => Boolean): A => Boolean =
a => p1(a) && p2(a)
And an identity value:
def id[A]: A => Boolean =
_ => true
which satisfies the condition that for any predicate p: A => Boolean, append(p, id) === p.
This simplifies the problem of including/excluding a predicate based on a condition: if the condition is false, simply include the id predicate. It has no effect on the filter because it always returns true.
To sum the predicates:
def sum[A](ps: List[A => Boolean]): A => Boolean =
ps.foldLeft[A => Boolean](id)(append)
Note that we fold onto id, so if ps is empty, we get the identity predicate, i.e. a filter that does nothing, as you'd expect.
Putting this all together:
val predicates = List(cond1 -> f1 _, cond2 -> f2 _)
strs.filter(sum(predicates.collect { case (cond, p) if cond => p }))
// List(hello, world)
Note that the list strs was only traversed once.
Now, for the Scalaz version of the above:
val predicates = List(cond1 -> f1 _, cond2 -> f2 _)
strs filter predicates.foldMap {
case (cond, p) => cond ?? (p andThen (_.conjunction))
}
// List("hello", "world")
#Noah's answer is good, and you can take it and generalize it further if you want to be able to perform any type of action on a list then returns a new List given a condition if you make the following change:
implicit class FilterHelper[A](l: List[A]) {
def ifthen[B](cond: Boolean, f:(List[A]) => List[B]) = {
if (cond) f(l) else l
}
}
Then use it like this:
val list = List("1", "2")
val l2 = list.ifthen(someCondition, _.filter(f1)
val l3 = list.ifthen(someOtherCondition, _.map(_.size))
It would be rather simple to just include the condition in your block for the filter, like so:
val result = strs filter (x => !cond1 || f1(x)) filter (x => !cond2 || f2(x))
whereby the result would apply a filter if the condition is met, or simply return the same list.
Given a sequence of elements and a predicate p, I would like to produce a sequence of sequences such that, in each subsequence, either all elements satisfy p or the sequence has length 1. Additionally, calling .flatten on the result should give me back my original sequence (so no re-ordering of elements).
For instance, given:
val l = List(2, 4, -6, 3, 1, 8, 7, 10, 0)
val p = (i : Int) => i % 2 == 0
I would like magic(l,p) to produce:
List(List(2, 4, -6), List(3), List(1), List(8), List(7), List(10, 0))
I know of .span, but that method stops the first time it encounters a value that doesn't satisfy p and just returns a pair.
Below is a candidate implementation. It does what I want, but, well, makes we want to cry. I would love for someone to come up with something slightly more idiomatic.
def magic[T](elems : Seq[T], p : T=>Boolean) : Seq[Seq[T]] = {
val loop = elems.foldLeft[(Boolean,Seq[Seq[T]])]((false,Seq.empty)) { (pr,e) =>
val (lastOK,s) = pr
if(lastOK && p(e)) {
(true, s.init :+ (s.last :+ e))
} else {
(p(e), s :+ Seq(e))
}
}
loop._2
}
(Note that I do not particularly care about preserving the actual type of the Seq.)
I would not use foldLeft. It's just a simple recursion of span with a special rule if the head doesn't match the predicate:
def magic[T](elems: Seq[T], p: T => Boolean): Seq[Seq[T]] =
elems match {
case Seq() => Seq()
case Seq(head, tail # _*) if !p(head) => Seq(head) +: magic(tail, p)
case xs =>
val (prefix, rest) = xs span p
prefix +: magic(rest, p)
}
You could also do it tail-recursive, but you need to remember to reverse the output if you're prepending (as is sensible):
def magic[T](elems: Seq[T], p: T => Boolean): Seq[Seq[T]] = {
def iter(elems: Seq[T], out: Seq[Seq[T]]) : Seq[Seq[T]] =
elems match {
case Seq() => out.reverse
case Seq(head, tail # _*) if !p(head) => iter(tail, Seq(head) +: out)
case xs =>
val (prefix, rest) = xs span p
iter(rest, prefix +: out)
}
iter(elems, Seq())
}
For this task you can use takeWhile and drop combined with a little pattern matching an recursion:
def magic[T](elems : Seq[T], p : T=>Boolean) : Seq[Seq[T]] = {
def magic(elems: Seq[T], result: Seq[Seq[T]]): Seq[Seq[T]] = elems.takeWhile(p) match {
// if elems is Nil, we have a result
case Nil if elems.isEmpty => result
// if it's not, but we don't get any values from takeWhile, we take a single elem
case Nil => magic(elems.tail, result :+ Seq(elems.head))
// takeWhile gave us something, so we add it to the result
// and drop as many elements from elems, as takeWhile gave us
case xs => magic(elems.drop(xs.size), result :+ xs)
}
magic(elems, Seq())
}
Another solution using a fold:
def magicFilter[T](seq: Seq[T], p: T => Boolean): Seq[Seq[T]] = {
val (filtered, current) = (seq foldLeft (Seq[Seq[T]](), Seq[T]())) {
case ((filtered, current), element) if p(element) => (filtered, current :+ element)
case ((filtered, current), element) if !current.isEmpty => (filtered :+ current :+ Seq(element), Seq())
case ((filtered, current), element) => (filtered :+ Seq(element), Seq())
}
if (!current.isEmpty) filtered :+ current else filtered
}
I am trying to process a tuple, where one of the cases is that the two values are equal. Is there a better, more concise way to match on this than
(p, q) match {
case (p, q) if (p == q) => println("Match!")
...
}
?
Personally, I think the way you've done it is great because it's simple, intuitive, and clear to the reader what's going on.
That said, here's one way you could do it without an if clause. You could just match on the swapped version, using backticks to turn q into stable identifiers. As #Luigi pointed out, you can just check that p matches q:
(p, q) match {
case (`q`, _) => println("Match!")
...
}
Like this:
def f(p: Int, q: Int) {
(p, q) match {
case (`q`, _) => println("Match!")
case _ => println("No")
}
}
f(1, 2) // "No"
f(1, 1) // "Match!"
You can define your own extractor:
object Eq {
def unapply[T](pair:(T,T)):Option[T] =
if (pair._1 == pair._2) Some(pair._1) else None
}
Then (4,4) match { case Eq(n) => println("same: " + n) } prints same: 4, while (3,4) wouldn't match.
I listed some comparision extractors in my blog (sorry, it's in German).
You can swap the values and then compare the tuple with its normal equals-method:
scala> val t = (1, 1)
t: (Int, Int) = (1,1)
scala> t.swap == t
res0: Boolean = true
scala> val t = (1, 2)
t: (Int, Int) = (1,2)
scala> t.swap == t
res1: Boolean = false
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))