Validate that sequence of numbers are within allowed range - scala

How can I validate that a sequence of numbers falls into an allowed range of numbers in a more scala/functional (not java like) way?
val valuesRight = Seq(1, 2, 3, 4, 5, 6, 7)
val valuesWrong = Seq(1, 2, 5, 6, 7, 8, 9)
val allowedValues = Range(1, 8)
def containsNotAllowedValues(allowed: Range, input: Seq[Int]): Boolean = {
var containsNotAllowedValue = false
// pseudo code of how to do it in java, But how in scala / functional way?
while next element is available
validate if it is contained in allowed
if not allowed set containsNotAllowedValue to true and break the loop early
}
containsNotAllowedValue
}
containsNotAllowedValues(allowedValues, valuesRight) // expected false as no wrong element contained
containsNotAllowedValues(allowedValues, valuesWrong) // expected true as at least single wrong element is contained

You can use the forall function on Seq. It checks whether the given predicate is true for all elements in the Seq. If that function returns false with the predicate allowed contains _, then your Seq contains an illegal value.
def containsNotAllowedValues(allowed: Range, input: Seq[Int]): Boolean =
!input.forall { allowed contains _ }

You could do something as simple as this:
def containsNotAllowedValues(allowed: Range, input: Seq[Int]): Boolean = {
!(allowed.head <= input.min && allowed.last >= input.max)
}
val valuesRight = Seq(1, 2, 3, 4, 5, 6, 7)
val valuesWrong = Seq(1, 2, 5, 6, 7, 8, 9)
val allowedValues = Range(1, 8)
containsNotAllowedValues(allowedValues,valuesRight) //false
containsNotAllowedValues(allowedValues,valuesWrong) //true
This will fail if the Range has only 1 value like Range(1,1)
If you want you can add
allowed.size>1
to catch those cases

Related

How to write filter with limit on Scala?

Let I have big array of some structure (in example below Int is for simplicity) and want to filter this array and take first n elements. How can I do it?
Example:
val outerVar = 22
def filterFunction(a: Int): Boolean = {
if (true/* some condition into this */) return false
if (a > 12) return true
if (a > 750) return false
if (a == 42) return true
if (a == outerVar) return true
// etc conditions that can use context of outer space
false
}
val n = 42
val bigArray = Array(1, 2, 3, 4, 5)
val result = bigArray.filter(element => {
filterFunction(element)
})
//.limit(n) (something like)
// how to stop filling result after it will contain n elements?
I believe, your predicate filterFunction is not going to do its work, since it always returns false.
Let's consider a toy example where we have an Array[Int] and we need to apply filter on it with predicate filterFunction so that the evaluation stops once n elements have been fetched:
scala> :paste
// Entering paste mode (ctrl-D to finish)
val array = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val filterFunction = (a: Int) => a > 5
val getLazy = (n: Int) => array.view.filter(filterFunction).take(n).toArray
getLazy(2)
// Exiting paste mode, now interpreting.
array: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
filterFunction: Int => Boolean = <function1>
getLazy: Int => Array[Int] = <function1>
res0: Array[Int] = Array(6, 7)
array.view.filter(filterFunction).take(n) becomes lazy expression (which is not evaluated right away) and toArray in fact runs the calculations.

Applying a predicate to all elements of a sequence

How should I write a function that returns true if all elements in a list satisfy a given predicate?
Considering list below and any predicate:
val set = List(3, 4, 5, 6, 10)
I assume I need to write something similar to:
def checkListElements(list parameters... ): Boolean = true if condition meet else false
You don't need to write one yourself, you can use Iterator.forall:
scala> var list = List(1,2,3,4,5)
set: List[Int] = List(1, 2, 3, 4, 5)
scala> list.forall(i => i % 2 == 0)
res0: Boolean = false
A little shorter using syntax sugar:
scala> list.forall(_ % 2 == 0) // Underscore will expand to i => i % 2 == 0
res2: Boolean = false

Scala collection select elements until first one meet a requirement

For example I have following Scala list, I want get a sublist until there is a requirement can be met.
val list = Seq(1,2,3,4,5,5,4,1,2,5)
The requirement is the number is 5, so I want the result as:
Seq(1,2,3,4)
Currently I use Scala collection's indexWhere and splitAt to return:
list.splitAt(list.indexWhere(x => x == 5))
(Seq(1,2,3,4), Seq(5,5,4,1,2,5))
I am not sure there are more better ways to achieve the same with better Scala collection's method I didn't realise?
You can use takeWhile:
scala> val list = Seq(1,2,3,4,5,5,4,1,2,5)
list: Seq[Int] = List(1, 2, 3, 4, 5, 5, 4, 1, 2, 5)
scala> list.takeWhile(_ != 5)
res30: Seq[Int] = List(1, 2, 3, 4)
Use span like this,
val (l,r) = list.span(_ != 5)
which delivers
l: List(1, 2, 3, 4)
r: List(5, 5, 4, 1, 2, 5)
Alternatively, you can write
val l = list.span(_ != 5)._1
to access only the first element of the resulting tuple.
This bisects the list at the first element that does not hold the condition.

How to take the first distinct (until the moment) elements of a list?

I am sure there is an elegant/funny way of doing it,
but I can only think of a more or less complicated recursive solution.
Rephrasing:
Is there any standard lib (collections) method nor simple combination of them to take the first distinct elements of a list?
scala> val s = Seq(3, 5, 4, 1, 5, 7, 1, 2)
s: Seq[Int] = List(3, 5, 4, 1, 5, 7, 1, 2)
scala> s.takeWhileDistinct //Would return Seq(3,5,4,1), it should preserve the original order and ignore posterior occurrences of distinct values like 7 and 2.
If you want it to be fast-ish, then
{ val hs = scala.collection.mutable.HashSet[Int]()
s.takeWhile{ hs.add } }
will do the trick. (Extra braces prevent leaking the temp value hs.)
This is a short approach in a maximum of O(2logN).
implicit class ListOps[T](val s: Seq[T]) {
def takeWhileDistinct: Seq[T] = {
s.indexWhere(x => { s.count(x==) > 1 }) match {
case ind if (ind > 0) => s.take(
s.indexWhere(x => { s.count(x==) > 1 }, ind + 1) + ind).distinct
case _ => s
}
}
}
val ex = Seq(3, 5, 4, 5, 7, 1)
val ex2 = Seq(3, 5, 4, 1, 5, 7, 1, 5)
println(ex.takeWhileDistinct.mkString(", ")) // 3, 4, 5
println(ex2.takeWhileDistinct.mkString(", ")) // 3, 4, 5, 1
Look here for live results.
Interesting problem. Here's an alternative. First, let's get the stream of s so we can avoid unnecessary work (though the overhead is likely to be greater than the saved work, sadly).
val s = Seq(3, 5, 4, 5, 7, 1)
val ss = s.toStream
Now we can build s again, but keeping track of whether there are repetitions or not, and stopping at the first one:
val newS = ss.scanLeft(Seq[Int]() -> false) {
case ((seen, stop), current) =>
if (stop || (seen contains current)) (seen, true)
else ((seen :+ current, false))
}
Now all that's left is take the last element without repetition, and drop the flag:
val noRepetitionsS = newS.takeWhile(!_._2).last._1
A variation on Rex's (though I prefer his...)
This one is functional throughout, using the little-seen scanLeft method.
val prevs = xs.scanLeft(Set.empty[Int])(_ + _)
(xs zip prevs) takeWhile { case (x,prev) => !prev(x) } map {_._1}
UPDATE
And a lazy version (using iterators, for moar efficiency):
val prevs = xs.iterator.scanLeft(Set.empty[Int])(_ + _)
(prevs zip xs.iterator) takeWhile { case (prev,x) => !prev(x) } map {_._2}
Turn the resulting iterator back to a sequence if you want, but this'll also work nicely with iterators on both the input AND the output.
The problem is simpler than the std lib function I was looking for (takeWhileConditionOverListOfAllAlreadyTraversedItems):
scala> val s = Seq(3, 5, 4, 1, 5, 7, 1, 2)
scala> s.zip(s.distinct).takeWhile{case(a,b)=>a==b}.map(_._1)
res20: Seq[Int] = List(3, 5, 4, 1)

Scala: How to sort an array within a specified range of indices?

And I have a comparison function "compr" already in the code to compare two values.
I want something like this:
Sorting.stableSort(arr[i,j] , compr)
where arr[i,j] is a range of element in array.
Take the slice as a view, sort and copy it back (or take a slice as a working buffer).
scala> val vs = Array(3,2,8,5,4,9,1,10,6,7)
vs: Array[Int] = Array(3, 2, 8, 5, 4, 9, 1, 10, 6, 7)
scala> vs.view(2,5).toSeq.sorted.copyToArray(vs,2)
scala> vs
res31: Array[Int] = Array(3, 2, 4, 5, 8, 9, 1, 10, 6, 7)
Outside the REPL, the extra .toSeq isn't needed:
vs.view(2,5).sorted.copyToArray(vs,2)
Updated:
scala 2.13.8> val vs = Array(3, 2, 8, 5, 4, 9, 1, 10, 6, 7)
val vs: Array[Int] = Array(3, 2, 8, 5, 4, 9, 1, 10, 6, 7)
scala 2.13.8> vs.view.slice(2,5).sorted.copyToArray(vs,2)
val res0: Int = 3
scala 2.13.8> vs
val res1: Array[Int] = Array(3, 2, 4, 5, 8, 9, 1, 10, 6, 7)
Split array into three parts, sort middle part and then concat them, not the most efficient way, but this is FP who cares about performance =)
val sorted =
for {
first <- l.take(FROM)
sortingPart <- l.slice(FROM, UNTIL)
lastPart <- l.takeRight(UNTIL)
} yield (first ++ Sorter.sort(sortingPart) ++ lastPart)
Something like that:
def stableSort[T](x: Seq[T], i: Int, j: Int, comp: (T,T) => Boolean ):Seq[T] = {
x.take(i) ++ x.slice(i,j).sortWith(comp) ++ x.drop(i+j-1)
}
def comp: (Int,Int) => Boolean = { case (x1,x2) => x1 < x2 }
val x = Array(1,9,5,6,3)
stableSort(x,1,4, comp)
// > res0: Seq[Int] = ArrayBuffer(1, 5, 6, 9, 3)
If your class implements Ordering it would be less cumbersome.
This should be as good as you can get without reimplementing the sort. Creates just one extra array with the size of the slice to be sorted.
def stableSort[K:reflect.ClassTag](xs:Array[K], from:Int, to:Int, comp:(K,K) => Boolean) : Unit = {
val tmp = xs.slice(from,to)
scala.util.Sorting.stableSort(tmp, comp)
tmp.copyToArray(xs, from)
}