I want to create a list from the n+1th value till n.length , where n is the value passed to a function
def test(n:String) ={
val list = List("1","12","30","40","50")
list match{
case s::rest if s==n => Seq(rest).flatten
case _ => Nil
}
}
if "12" is passed , I get a empty list.
Expected Output = List("30,40,50")
Putting it another way, you want to remove the first n values from the list. For this, you use drop:
list.drop(n)
If you want to drop values based on a condition, use dropWhile:
list.dropWhile(_ != "30")
To exclude the matching element, use another drop:
list.dropWhile(_ != "12").drop(1)
[ As noted in the comments, using tail could cause exception if the element is not found ]
Related
With Scala 2.12, I am looping an array with pattern matching to create a new array as below.
val arrNew=arrText.map {
case x if x.startsWith("A") =>x.substring(12, 20)
case x if x.startsWith("B") =>x.substring(21, 40)
case x => "0"
}.filter(_!="0")
If an element matches one of the two patterns, a new element is added into the new array arrNew. Those that do not match will be dropped. My codes actually loop arrText twice with filter. If I do not include case x =>"0", there will be errors complaining some elements are not getting matched. Are the codes below the only way of looping just once? Any way I can loop only once with case matching?
map { x =>
if (condition1) (output1)
else if (condition2) (output2)
}
you can use collect
[use case] Builds a new collection by applying a partial function to all elements of this sequence on which the function is defined.
val arrNew=arrText.collect {
case x if x.startsWith("A") =>x.substring(12, 20)
case x if x.startsWith("B") =>x.substring(21, 40)
}
I have a input file like this:
The Works of Shakespeare, by William Shakespeare
Language: English
and I want to use flatMap with the combinations method to get the K-V pairs per line.
This is what I do:
var pairs = input.flatMap{line =>
line.split("[\\s*$&#/\"'\\,.:;?!\\[\\(){}<>~\\-_]+")
.filter(_.matches("[A-Za-z]+"))
.combinations(2)
.toSeq
.map{ case array => array(0) -> array(1)}
}
I got 17 pairs after this, but missed 2 of them: (by,shakespeare) and (william,shakespeare). I think there might be something wrong with the last word of the first sentence, but I don't know how to solve it, can anyone tell me?
The combinations method will not give duplicates even if the values are in the opposite order. So the values you are missing already appear in the solution in the other order.
This code will create all ordered pairs of words in the text.
for {
line <- input
t <- line.split("""\W+""").tails if t.length > 1
a = t.head
b <- t.tail
} yield a -> b
Here is the description of the tails method:
Iterates over the tails of this traversable collection. The first value will be this traversable collection and the final one will be an empty traversable collection, with the intervening values the results of successive applications of tail.
I have a List[Either[Error, Satisfaction]], and I need to take the first element in that list that isRight. If there are no elements that satisfy isRight, then I should return the last Error.
For now I've thought on a takeWhile(_.isLeft), find the size of this last list, and then get the nth element in the original list, with n being the size of the first-lefts list, but I think there's a better solution for this.
Any help will be strongly appreciated.
You might reduce the list like so:
lst.reduceLeft((a,b) => if (a.isRight) a else b)
The result will be the first Right element or, if there is none, the final Left element.
You can do this, which has the dual problem to #jwvh's answer: if rest is empty, it has to go over the list again.
val (lefts, rest) = list.span(_.isLeft)
rest.headOption.getOrElse(lefts.last)
// or orElse(lefts.lastOption) if list can be empty
And the recursive solution without either problem for completeness (assuming non-empty list):
def foo(list: List[Either[Error, Satisfaction]]) = list match {
case x :: tail => if (x.isRight || tail.isEmpty) x else foo(tail)
}
Not that much more code.
I have a tuple like the following:
(Age, List(19,17,11,3,2))
and I would like to get the position of the first element where their position in the list is greater than their value. To do this I tried to use .indexOf() and .indexWhere() but I probably can't find exactly the right syntax and so I keep getting:
value indexWhere is not a member of org.apache.spark.rdd.RDD[(String,
Iterable[Int])]
My code so far is:
val test =("Age", List(19,17,11,3,2))
test.indexWhere(_.2(_)<=_.2(_).indexOf(_.2(_)) )
I also searched the documentation here with no result: http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.List
If you want to perform this for each element in an RDD, you can use RDD's mapValues (which would only map the right-hand-side of the tuple) and pass a function that uses indexWhere:
rdd.mapValues(_.zipWithIndex.indexWhere { case (v, i) => i+1 > v} + 1)
Notes:
Your example seems wrong, if you want the last matching item it should be 5 (position of 2) and not 4
You did not define what should be done when no item matches your condition, e.g. for List(0,0,0) - in this case the result would be 0 but not sure that's what you need
One of my exercises requires me to write a recursive method in which a list is given, and it returns the same list with only every other element on it.
for example : List {"a", "b", "c"} would return
List{"a","c"}
I am writing in scala, and I understand that it has built in library but I am not supposed to use those. I can only use if/else, helper methods,and patterns.
How could I parse thru a list using head and tail only?
so far I have this:
def removeLetter(list:List[String]):List[String]=list match{
case Nil => Nil
case n::rest=>
if (n == rest){ // I understand that this doesn't quite work.
tail
}
else
head::removeLetter(tail)
}
}
I am looking for the logic and not code.
Using pattern matching, you can also deconstruct a list on it's first two elements in the same way you're doing with your n::rest construction. Just remember to also take lists with uneven length into account.
You correctly stated one base-case to the recursion: In case of an empty list, the result is again the empty list. case Nil => Nil
There is a second base-case: A list containing a single element is again the list itself. case x :: Nil => x :: Nil
You can formulate the recursive step as follows: Given a list with at least two elements, the result is a list containing the first element, followed by every other element of the list after the second element. case x :: y :: z => x :: removeLetter(z) (Note that here, x and y are both of type String while z is of type List[String])
Remark: If you wanted to, you could also combine both base-cases, as in both cases, the input to the function is its output.