I'm solving a problem on leetcode-
https://leetcode.com/problems/minimum-absolute-difference/
I can't seem to understand why in the code below the result list is not correctly appended after resetting it to nil.
I looked online of course but could not fathom the concept behind this behavior. Can someone explain why after result is assigned Nil, no value can get added to that list? How do I reset the list?
I tried with ListBuffer and clear() but I got the same issue, at the end of the run the result is Nil
Expected behavior:
Input: arr = [4,2,1,3]
Output: [[1,2],[2,3],[3,4]]
Actual behavior:
Input: arr = [4,2,1,3]
Output: List()
def minimumAbsDifference(arr: Array[Int]): List[List[Int]] = {
val sortedInput = arr.sorted
var min = Integer.MAX_VALUE
var result = Seq[List[Int]]()
for(i <- 0 until sortedInput.length - 1){
val diff = sortedInput(i+1) - sortedInput(i)
if(min > diff){
result = Nil
min = diff
}
if(min == diff){
result :+ List(sortedInput(i),sortedInput(i+1))
}
}
result.toList
}
You're assigning Nil to result and then never assigning anything else.
Because List is immutable result :+ List(...) returns a new list which is then thrown away. You need to assign the new list to result.
A couple of other notes:
It is extremely inefficient (decidedly not "leet") to append to a list. It's much more efficient to prepend (building the result in reverse) and then reverse at the end.
It is also extremely inefficient to access List items by index.
Use of var should generally be avoided in Scala, though this particular usage (contained locally to an otherwise pure function) is not beyond the pale.
Related
I have a string, lets say val mystr = "abcde", and I want to find the minimal substring of mystr which satisfies a given condition. I have to send a string to an external system, so the only way to do this is to iterate through the length of the string and make requests to the external system, and break when the response from the external system returns true
eg.
callExtSystemWith("a") //Returns false
callExtSystemWith("ab") //Returns false
callExtSystemWith("abc") //Returns true
Then my method should return "abc". I read that breaks are not the scala way, so was wondering what is the scala way of achieving this?
Right now I have:
for {end <- 1 to mystr.length)}{
callExtSystemWith(mystr.substring(0,end))
// I Want to break when this is true.
}
Help much appreciated
You can use inits.toStream.reverse.drop(1) (1 to s.length).map(s.take).toStream to create a lazy stream with a, ab, abc, abcd.
Then filter those strings, so that only the ones for which callExtSystemWith returns true are left.
Then get the first string for which callExtSystemWith returns true. Because this is a lazy stream, no unecessary requests will be made to the server once the first match is found.
val s = "abcdefgh"
val strs = (1 to s.length).map(s.take).toStream
strs.filter(callExtSystemWith).headOption match {
case Some(s) => "found"
case _ => "not found"
}
You can also use find instead of filter + headOption
Quite often break can be replaced with find on some sequence
So here is another short solution for this problem:
def findSuitablePrefix(mystr: String): Option[String] =
(1 to mystr.length).view.map(mystr.substring(0, _)).find(callExtSystemWith)
.view makes the evaluation lazy to avoid creating extra substrings.
.map transforms the sequence of indexes into a sequence of substrings.
And .find "breaks" after the first element for which callExtSystemWith returns true is found.
In Scala there are no normal breaks but there are other solutions. The one I like better is to create a function and force a return (instead of a normal break). Something like:
def callAndBreak(mystr:String) : Int = {
for (end <- 1 to mystr.length) {
if ( callExtSystemWith(mystr.substring(0,end)) ) return end
}
end
}
Here I return end but you can return anything
If you want to avoid using return or breaks, you could also use foldLeft:
val finalResult = (1 to mystr.length).foldLeft(false) { (result, end) =>
if(!result) callExtSystemWith(mystr.substring(0, end)) else result
}
However, it is a bit hard to read, and will walk the entire length of the string.
Simple recursion might be a better way:
def go(s: String, end: Int): Boolean = {
if(end >= s.length) false
else {
callExtSystemWith(s.substring(0, end)) || go(s, end + 1)
}
}
go(mystr, 1)
I am new to Scala and I have a function as follows:
def selectSame(messages: BufferedIterator[Int]) = {
val head = messages.head
messages.takeWhile(_ == head)
}
Which is selecting from a buffered iterator only the elems matching the head. I am subsequently using this code:
val messageStream = List(1,1,1,2,2,3,3)
if (!messageStream.isEmpty) {
var lastTimeStamp = messageStream.head.timestamp
while (!messageStream.isEmpty) {
val messages = selectSame(messageStream).toList
println(messages)
}
Upon first execution I am getting (1,1,1) as expected, but then I only get the List(2), like if I lost one element down the line... Probably I am doing sth wrong with the iterators/lists, but I am a bit lost here.
Scaladoc of Iterator says about takeWhile:
Reuse: After calling this method, one should discard the iterator it
was called on, and use only the iterator that was returned. Using the
old iterator is undefined, subject to change, and may result in
changes to the new iterator as well.
So that's why. This basically means you cannot directly do what you want with Iterators and takeWhile. IMHO, easiest would be to quickly write your own recursive function to do that.
If you want to stick with Iterators, you could use the sameElements method on the Iterator to generate a duplicate where you'd call dropWhile.
Even better: Use span repeatedly:
def selectSame(messages: BufferedIterator[Int]) = {
val head = messages.head
messages.span(_ == head)
}
def iter(msgStream: BufferedIterator[Int]): Unit = if (!msgStream.isEmpty) {
val (msgs, rest) = selectSame(msgStream)
println(msgs.toList)
iter(rest)
}
val messageStream = List(1,1,1,2,2,3,3)
if (!messageStream.isEmpty) {
var lastTimeStamp = messageStream.head.timestamp
iter(messageStream0
}
I am running the following piece of code:
val it = List(1,1,1,2,2,3,3).iterator.buffered
val compare = it.head
it.takeWhile(_ == compare).toList
and it returns (1,1,1). However, if I run this as:
val it = List(1,1,1,2,2,3,3).iterator.buffered
it.takeWhile(_ == it.head).toList
I am getting (1,1). Why is this the case? Isn't head evaluated upon calling takeWhile and the result should be the same?
Because the iterator is mutable, the value of it.head depends on when it is evaluated.
Inspecting the implementation of takeWhile reveals that it removes the head of the iterator before applying the predicate.
So, on the third iteration, it.head evaluated from within the predicate will be 2, because the third element has already been removed.
This is an illustration of why you should prefer immutability. It rules out a whole class of non-obvious behaviour like this.
Adding to #Ben James answer above. Below is takeWhile method code (credits: ben):
def hasNext = hdDefined || tail.hasNext && {
hd = tail.next() //line 2
if (p(hd)) hdDefined = true
else tail = Iterator.empty
hdDefined
}
In the third iteration after line 2, the value is: hd=1 and remaining Iterator is List(2,2,3,3). on calling p(hd), it checks the iterator's head which in this case is 2. Hence it breaks.
Please check this
import scala.collection.mutable.LinkedList
var l = new LinkedList[String]
l append LinkedList("abc", "asd")
println(l)
// prints
// LinkedList()
but
import scala.collection.mutable.LinkedList
var l = new LinkedList[String]
l = LinkedList("x")
l append LinkedList("abc", "asd")
println(l)
// prints
// LinkedList(x, abc, asd)
Why does the second code snippet works but the first one doesnt? This is on Scala 2.10
The documentation says If this is empty then it does nothing and returns that. Otherwise, appends that to this.. That is exactly, what you observed. If you really need a mutable list, I would suggest you to use scala.collection.mutable.ListBuffer instead, with it you can do
val lb = new ListBuffer[Int]
scala> lb += 1
res14: lb.type = ListBuffer(1)
scala> lb
res15: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1)
scala> lb ++= Seq(1,2,3)
res17: lb.type = ListBuffer(1, 1, 2, 3, 1, 2, 3)
scala> lb
res18: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 1, 2, 3, 1, 2, 3)
As I understand it is related to First/Last (Nil) element in the list (if list is empty Nil is first and last element at the same time).
LinkedList (still) follows "primitive charm" strategy. So it does not try to add/append new data to/after Nil, to have possible result like this: {Nil, newElement}. (After all Nil should be last element)
Of course it could check if list is empty then put addingList to the beginning and Nil to the end. But this would be "too smart", I guess.
But, anyway append() returns "expecting" result Like this:
val addingList = new LinkedList[String]("a", "b")
val result = emptyList append addingList
result = {"a", "b"}. In this case it returns 'addingList' itself, and/but does not change initial list.
If we try to assign newElement to the next ref:
emptyList.next = LinkedList("whatever")
As result we would have emtyList changed like this:
LinkedList(null, whatever)
I.e. it creates fist element as null, since we have used next() assigning new/next element to it. So it moves Nil to the end, because first element which is null, has next reference to new element we added (addingElelement).
Because
"the "emptyList" is also the "head" link"
and head in our case head is Nil, but Nill can not have next, so it has to create new first element (which is has null value) with next() referece to our new addingElelement.
Personally I find it "too much primitive" and not "so much elegant". But it depends, I guess.
Task oriented story:
For my initial task (why I start thinking about this 'strange' list behaviour [even though it's mutable]) -- I wanted to use mutable list for a class/object called Dictionary which would keep Words in it (dictionary by default has not any words). And I would have methods like addWord(wod:String) for adding new words. For now my implementation will be changed (I'm not going to use this LinkedList, but rather MutableList. It seems it is more mutable than previous one):
object Dictionary {
val words = new mutable.MutableList[Word]();
def addWord(word: Word): Unit = {
words += word;
}
}
But possible implementation could be like this:
object Dictionary {
var words = new mutable.LinkedList[Word]();
def addWord(word: Word): Unit = {
if (words.isEmpty) {
words = words append( mutable.LinkedList[Word](word) ) // rely on append result
} else {
words append( mutable.LinkedList[Word](word) )
}
}
}
But then I have to use var instead of val, and I should transform every new Word to LinkedList, and my logic became more complicated.
For example suppose I have
for (line <- myData) {
println("}, {")
}
Is there a way to get the last line to print
println("}")
Can you refactor your code to take advantage of built-in mkString?
scala> List(1, 2, 3).mkString("{", "}, {", "}")
res1: String = {1}, {2}, {3}
Before going any further, I'd recommend you avoid println in a for-comprehension. It can sometimes be useful for tracking down a bug that occurs in the middle of a collection, but otherwise leads to code that's harder to refactor and test.
More generally, life usually becomes easier if you can restrict where any sort of side-effect occurs. So instead of:
for (line <- myData) {
println("}, {")
}
You can write:
val lines = for (line <- myData) yield "}, {"
println(lines mkString "\n")
I'm also going to take a guess here that you wanted the content of each line in the output!
val lines = for (line <- myData) yield (line + "}, {")
println(lines mkString "\n")
Though you'd be better off still if you just used mkString directly - that's what it's for!
val lines = myData.mkString("{", "\n}, {", "}")
println(lines)
Note how we're first producing a String, then printing it in a single operation. This approach can easily be split into separate methods and used to implement toString on your class, or to inspect the generated String in tests.
I agree fully with what has been said before about using mkstring, and distinguishing the first iteration rather than the last one. Would you still need to distinguish on the last, scala collections have an init method, which return all elements but the last.
So you can do
for(x <- coll.init) workOnNonLast(x)
workOnLast(coll.last)
(init and last being sort of the opposite of head and tail, which are the first and and all but first). Note however than depending on the structure, they may be costly. On Vector, all of them are fast. On List, while head and tail are basically free, init and last are both linear in the length of the list. headOption and lastOption may help you when the collection may be empty, replacing workOnlast by
for (x <- coll.lastOption) workOnLast(x)
You may take the addString function of the TraversableOncetrait as an example.
def addString(b: StringBuilder, start: String, sep: String, end: String): StringBuilder = {
var first = true
b append start
for (x <- self) {
if (first) {
b append x
first = false
} else {
b append sep
b append x
}
}
b append end
b
}
In your case, the separator is }, { and the end is }
If you don't want to use built-in mkString function, you can make something like
for (line <- lines)
if (line == lines.last) println("last")
else println(line)
UPDATE: As didierd mentioned in comments, this solution is wrong because last value can occurs several times, he provides better solution in his answer.
It is fine for Vectors, because last function takes "effectively constant time" for them, as for Lists, it takes linear time, so you can use pattern matching
#tailrec
def printLines[A](l: List[A]) {
l match {
case Nil =>
case x :: Nil => println("last")
case x :: xs => println(x); printLines(xs)
}
}
Other answers are rightfully pointed to mkString, and for a normal amount of data I would also use that.
However, mkString builds (accumulates) the end-result in-memory through a StringBuilder. This is not always desirable, depending on the amount of data we have.
In this case, if all we want is to "print" we don't need to build the big-result first (and maybe we even want to avoid this).
Consider the implementation of this helper function:
def forEachIsLast[A](iterator: Iterator[A])(operation: (A, Boolean) => Unit): Unit = {
while(iterator.hasNext) {
val element = iterator.next()
val isLast = !iterator.hasNext // if there is no "next", this is the last one
operation(element, isLast)
}
}
It iterates over all elements and invokes operation passing each element in turn, with a boolean value. The value is true if the element passed is the last one.
In your case it could be used like this:
forEachIsLast(myData) { (line, isLast) =>
if(isLast)
println("}")
else
println("}, {")
}
We have the following advantages here:
It operates on each element, one by one, without necessarily accumulating the result in memory (unless you want to).
Because it does not need to load the whole collection into memory to check its size, it's enough to ask the Iterator if it's exhausted or not. You could read data from a big file, or from the network, etc.