How to convert a Some(" ") to None in one-line?
Asked Answered
F

3

9

I want to define a function:

def convert(x: Option[String]): Option[String] = ...

When x is Some(str) and the str is empty after trimming, it will be converted to a None, otherwise, it will be a Some with trimmed string.

So, the test case will be:

convert(Some("")) == None
convert(Some("  ")) == None
convert(None) == None
convert(Some(" abc ")) == Some("abc")

I can write it as:

def convert(x: Option[String]): Option[String] = x match {
  case Some(str) if str.trim()!="" => Some(str.trim())
  case _ => None
}

But I hope to find a simpler implementation(one-line).

Flywheel answered 5/3, 2012 at 15:18 Comment(6)
Do you have some shortage of newline characters in your environment? Do you get paid inversely proportional to the number of lines you write? My advice would be to just use the two line version and stop making work for yourself :-)Lasseter
I just like to make my code simple and clearFlywheel
@paxdiablo: It is a valid question as the example can indeed be improved: The code runs str.trim twice which is clearly something to avoid.Feminacy
@paxdiablo: What Debilskli said. Also pattern matching on option can be avoided in most cases (such as this one). I appreciate OP's attitude of constantly wanting to find a better way of doing things.Strung
@Freewind, you might find this useful.Strung
I have no problem with finding a better way of doing something. My only issue is with people wasting time trying to convert a three line function into a one-line one. These people clearly have too much time on their hands :-) In retrospect, it may be that the operative word in the question was "simpler", but there was an inordinate amount of emphasis placed on the phrase "one line", which is why I commented.Lasseter
G
17

What about this:

def convert(x: Option[String]) = 
    x.map(_.trim()).filterNot(_.isEmpty())

UPDATE: Alternative syntaxes suggested by @JamesMoore and @PeterSchmitz:

x map {_.trim} filterNot {_.isEmpty}
x map (_.trim) filterNot (_.isEmpty)
Ganges answered 5/3, 2012 at 15:22 Comment(10)
Sorry, convert(Some(" abc ")) != Some("abc")Flywheel
I think it's easier to read if you drop the parens: x map {_.trim} filterNot {_.isEmpty}Unilocular
And I think it´s easier to read if you use round parens instead of curly ones :D x map (_.trim) filterNot (_.isEmpty)Coelostat
@JamesMoore: thanks for input, I added your suggestion to answer. In contrary, I find it easier to read compared to parens ;-).Ganges
@TomaszNurkiewicz interesting. Maybe I've just spent too much time with Ruby. IMHO, Scala normally requires vast amounts of line noise, and the more it can be reduced the better. (It's not as bad as java, but that's not high praise.) I think Peter's suggestion is fine too.Unilocular
@JamesMoore: by version with parens I meant James's one, not mine :-). I added it as well to my answer as it is even more upvoted comment. Thanks again both of you!Ganges
This is considered more "simple and clear" than the original?Arrio
@EdStaub: yes, original is very simple from imperative point of view. But this approach is simpler once you grasp how Option works. Think about it as a collection either being empty or having one element. The semantics of map and filterNot become clear.Ganges
@TomaszNurkiewicz: Thanks! My response is an off-topic question, so I posted it separately.Arrio
If you want to map a empty-when-trimmed string to None, but not actually trim the string, use this variation: x filterNot (_.trim.isEmpty)Calpac
A
1

And as usual there is also the for comprehension alternative syntax (which is a syntax sugar for filter and map)

 def convert(o: Option[String]): Option[String] = 
    for (x <- o if !x.isEmpty) yield x
Aleasealeatory answered 24/2, 2014 at 7:37 Comment(1)
More like syntactic vinegarCrazed
T
1

def convert(x: Option[String]) = x.filter(s => s.trim.nonEmpty)

Totalitarianism answered 11/5, 2016 at 14:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.