Appending list of optional elements - scala

I need to make a sequence that, given a list containing optional list of strings, concatenates all of them to make a new list. This how my code looks like:
res.foldLeft(Seq[Option[Seq[String]]]())((acc, v) => v match {
case Some(x) => acc ++: Some(x)
case None => acc
})
where res is a list containing optional list elements such as :
List(Some(Seq(foo)), Some(Seq(bar)), None, Some(Seq(baz, blah)))
I get a compilation error at the sign ++: saying:
type mismatch; found : Iterable[Equals] required: Seq[Option[Seq[String]]]
What am I doing wrong here?

Why don't you just do:
res.flatten.flatten
first flatten will get rid of Nones and expose the Options and second one will perform the expected flattening operation on the Seqs

I don't have scala installed on this box, but you could try using the 'map' function to remove the options out of the equation, then flatten the list of seq down to a single iterable.
Something like this:
res.map.flatten
As I understand it you would then end up with a Iterable containing 'foo', 'bar', 'sez', 'bar'.
I'll check this out a little later to test the syntax is correct and what I've written actually works..
Cheers, Aaron
EDIT: Got access to my scala terminal and this works:
res.map(s => s).flatten.flatten

Your types in case Some(x) => acc ++: Some(x) part is wrong.
++: operator expects a parameter of type Seq[Option[Seq[String]]] but you are providing a parameter of type Option[Seq[String]].
ps: If you can tell exactly the result you expect. I can improve this answer to help you to write the correct code you need.

Related

Convert Map of mutable Set of strings to Map of immutable set of strings in Scala

I have a "dirtyMap" which is immutable.Map[String, collection.mutable.Set[String]]. I want to convert dirtyMap to immutable Map[String, Set[String]]. Could you please let me know how to do this. I tried couple of ways that didn't produce positive result
Method 1: Using map function
dirtyMap.toSeq.map(e => {
val key = e._1
val value = e._2.to[Set]
e._1 -> e._2
}).toMap()
I'm getting syntax error
Method 2: Using foreach
dirtyMap.toSeq.foreach(e => {
val key = e._1
val value = e._2.to[Set]
e._1 -> e._2
}).toMap()
cannot apply toMap to output of foreach
Disclaimer: I am a Scala noob if you couldn't tell.
UPDATE: Method 1 works when I remove parenthesis from toMap() function. However, following is an elegant solution
dirtyMap.mapValues(v => v.toSet)
Thank you Gabriele for providing answer with a great explanation. Thanks Duelist and Debojit for your answer as well
You can simply do:
dirtyMap.mapValues(_.toSet)
mapValues will apply the function to only the values of the Map, and .toSet converts a mutable Set to an immutable one.
(I'm assuming dirtyMap is a collection.immutable.Map. In case it's a mutable one, just add toMap in the end)
If you're not familiar with the underscore syntax for lambdas, it's a shorthand for:
dirtyMap.mapValues(v => v.toSet)
Now, your first example doesn't compile because of the (). toMap takes no explicit arguments, but it takes an implicit argument. If you want the implicit argument to be inferred automatically, just remove the ().
The second example doesn't work because foreach returns Unit. This means that foreach executes side effects, but it doesn't return a value. If you want to chain transformations on a value, never use foreach, use map instead.
You can use
dirtyMap.map({case (k,v) => (k,v.toSet)})
You can use flatMap for it:
dirtyMap.flatMap(entry => Map[String, Set[String]](entry._1 -> entry._2.toSet)).toMap
Firstly you map each entry to immutable.Map(entry) with updated entry, where value is immutable.Set now. Your map looks like this: mutable.Map.
And then flatten is called, so you get mutable.Map with each entry with immutable.Set. And then toMap converts this map to to immutable.
This variant is complicated a bit, you simply can use dirtyMap.map(...).toMap as Debojit Paul mentioned.
Another variant is foldLeft:
dirtyMap.foldLeft(Map[String, Set[String]]())(
(map, entry) => map + (entry._1 -> entry._2.toSet)
)
You specify accumulator, which is immutable.Map and you add each entry to this map with converted Set.
As for me, I think using foldLeft is more effective way.

Implicit String to Seq[Char] pattern matching fail

Warning - this is a code which deals with Codility BinaryGap task - just to warn as this may spoil something to somebody.
I have a piece of code, like
#tailrec
def count2(max:Int, count:Int, d:Seq[Char]):Int = d match {
case '1' :: s => count2(Math.max(max, count), 0, s)
case '0' :: s => count2(max, count+1, s);
case Nil => max
}
I call it like
println(Solution.count2(0, 0, Seq('1', '0')))
println(Solution.count2(0, 0, "10"))
It compiles, however the second call does not work - throwing "Match not found 10" And I cannot understand why. There is a similar question around that topic which states, that explicit conversion is needed. However, I feel like I do have one in form of a method parameter type.
Debugger clearly states that d variable is of type WrappedString - which should do the job. But apparently, it does not.
What is going on here?
Your pattern matching is working only on a the type List[Char] while you are passing an object of type Seq[Char]. Therefore you will never actually match on the very first call. The reason it compiles is that match is not exhaustive for Seq. It is, however, exhaustive for List.
Update:
Let me point out two things:
The default constructor for Seq produces a List. So the first example "works."
The String you've given is implicitly convertable to a Seq[Char] but it is not a List! Hence, it will give you your match error.

Dealing with Type Erasure with foldLeft [duplicate]

I've trying to sort a list by a future boolean.
I have a list of IDs and I need to query an external service to find out if there's contextual information behind them. The method I use to do this returns an optional future.
By using the partition method I hoped to create two lists of IDs, one with contextual information and one without.
The following answer on here provided a lot of help for this: Scala - sort based on Future result predicate
I now have an rough, untested method that looks like so,
val futureMatch = listOfIds.map( b => b.map{ j =>
getContext(j).map{ k =>
Map( j -> k)
}
}).map(Future.sequence(_)).flatMap(identity)
val partitionedList = futureMatch.map(_.partition{
case (k, Some(v)) => true
case _ => false
})
So as advised in the other question, I'm attempting to get all my answers at the same level, and then using Future.sequence and flatMap(identity) to flatten nested layers of futures.
The problem is this doesn't feel very efficient.
Ideally the successful list would have a signature of List[Map[String, String]] not List[Map[String, Option[String]] and the failed list would just be a list of Strings, so it'd only need to be one dimensional. As it currently stands I have two identical list signatures which have some redundancy. For example in the successful list, I know this is going exist so it doesn't need to be an option.
Any ideas how I could achieve this structure and produce two lists with different signatures or even if this is the most efficient way.
Thanks.
EDIT: Looking at the signature for partition it looks like I can only produce two lists of the same signature, so a different signature is probably too much to ask. I guess I can just flatten the list afterwards.
I found a suitable solution in the comments of the question I linked too.
val (matched, unmatched) =
finalMatch.foldLeft(List.empty[Map[String, String]], List.empty[String]) {
case ((matched, unmatched), p) => p match {
case m:Map[String, String] => (m :: matched, unmatched)
case s:String => (matched, s :: unmatched)
}
}
The only issue with this is it leads to type erasure. I've opened another question to discuss this issue.
Dealing with Type Erasure with foldLeft
Thanks all.

What's the best way to open up a list with 0 or 1 options?

In Scala I have a List with an optional Option. This arises for example when you use for comprehension on a List and your yield returns an Option. In my case I was processing a JSON object and using for comprehension on the list of fields (List[JField]).
What's the best way to open up the list and map List() to None and List(Some(a)) to Some(a)?
A first approach would be
def headOrNone[A](list:List[Option[A]]) =
list match {
case Nil => None
case a::Nil => a
}
Another approach
def headOrNone[A](list:List[Option[A]]) = list.headOption.getOrElse(None)
A third approach (a variation on the headOption implementation)
def headOrNone[A](list:List[Option[A]]) = if (list.isEmpty) None else list.head
I personally prefer the third approach. Is there a better name for this function than headOrNone and what is the idiomatic scala way to write it?
You're solving a problem that probably shouldn't have been created. Instead, you probably want
for (x <- list) yield f(x) // Yields Option
to be
list.flatMap(f)
and then you'll have either zero or one things in your list to begin with (which you can extract using headOption).
How about this:
def headOrNone[A](list: List[Option[A]]) = list.flatten.headOption
headOrNone(List(Some(4))) // Some(4)
headOrNone(List()) // None
Though the first choice has the advantage of giving you an error if you happen to have list with more than one item, which, according to your description, seems like an error condition.
But personally, I would re-evaluate the code that produces the List[Option[A]] and see if there's a way to just have it return the right thing in the first place!

Scala "match" help

I am studying some scala code and found this method which baffles me. In the match statement, what is the sublist# construct? what kind of value does it contains? when I printed it its no diff than tail, but if I replace it with tail, the function returns diff result. Can somebody explain what it is and point me to a right resource to understand it? (I know I can search in google, but don't know what to look for..)
def flatMapSublists[A, B](ls: List[A])(f: (List[A]) => List[B]): List[B] =
ls match {
case Nil => Nil
case sublist#(_ :: tail) => f(sublist) ::: flatMapSublists(tail)(f)
}
I would call it the "eat your cake and have it too operator". At any level in pattern matching, you can give a part a name (before the #) and deconstruct it further (after the #). For instance imagine you want to match against a List with 3 elements, you need the second element, but you want to log the whole list:
something match {
case list#List(_,elem,_) => log("matching:" + list); elem
case _ => error("not found")
}
Without this feature, you had to write something like
something match {
case List(a,elem,b) => log("matching:" + List(a,elem,b)); elem
case _ => error("not found")
}
As you can see, we need to name the first and third element, just because we need them to get a list with the same structure on the right side, which is boilerplate. It is much easier and clearer if you can give the whole thing a name (list), and parts deeper in the structure as well (elem), when you need both on the right side.
In this instance, sublist becomes a named variable for the entire list (_ :: tail). tail is the, well, tail of the list. I'm not sure if there is a proper name for '#' here.
I don't really see the purpose of sublist here, since you can just reference ls directly.
Disclaimer: I'm new to scala. I hope I got this right.