Jack
Jack

Reputation: 16718

String concatenation gone functional

Suppose there are 3 strings:

protein, starch, drink

Concatenating those, we could say what is for dinner:

Example:

val protein = "fish"
val starch = "chips"
val drink = "wine"

val dinner = protein + ", " + starch + ", " + drink

But what if something was missing, for example the protein, because my wife couldn't catch anything. Then, we will have: ,chips, drink for dinner.

There is a slick way to concatenate the strings to optionally add the commas - I just don't know what it is ;-). Does anyone have a nice idea?

I'm looking for something like:

val dinner = protein +[add a comma if protein is not lenth of zero] + starch .....

It's just a fun exercise I'm doing, so now sweat if it can't be done in some cool way. The reason that I'm trying to do the conditional concatenation in a single assignment, is because I'm using this type of thing a lot in XML and a nice solution will make things..... nicer.

Upvotes: 28

Views: 33499

Answers (5)

Deepak Saxena
Deepak Saxena

Reputation: 1

println(s"$protein,$starch,$drink")

Upvotes: -4

Alexander Azarov
Alexander Azarov

Reputation: 13221

When you say "it may be absent", this entity's type should be Option[T]. Then,

def dinner(components: List[Option[String]]) = components.flatten mkString ", "

You would invoke it like this:

scala> dinner(None :: Some("chips") :: Some("wine") :: Nil)
res0: String = chips, wine

In case you absolutely want checking a string's emptiness,

def dinner(strings: List[String]) = strings filter {_.nonEmpty} mkString ", "

scala> dinner("" :: "chips" :: "wine" :: Nil)
res1: String = chips, wine

Upvotes: 40

Jesse
Jesse

Reputation: 489

This takes care of the case of empty strings and also shows how you could put other logic for filtering and formatting. This will work fine for a List[String] and generalizes to List[Any].

val input = List("fish", "", "chips", 137, 32, 32.0, None, "wine")

val output = input.flatMap{ _ match { 
  case None => None
  case x:String if !x.nonEmpty => None
  case x:String => Some(x)
  case _ => None
}}
.mkString(",")

res1: String = fish,chips,wine

The idea is that flatMap takes a List[Any] and uses matching to assign None for any elements that you do not want to keep in the output. The Nones get flattened away and the Somes stay.

If you needed to be able to handle different types (Int, Double, etc) then you could add more cases.

Upvotes: 5

Daniel C. Sobral
Daniel C. Sobral

Reputation: 297205

scala> def concat(ss: String*) = ss filter (_.nonEmpty) mkString ", "
concat: (ss: String*)String

scala> concat("fish", "chips", "wine")
res0: String = fish, chips, wine

scala> concat("", "chips", "wine")
res1: String = chips, wine

scala>

Upvotes: 13

user unknown
user unknown

Reputation: 36229

You're looking for mkString on collections, maybe.

val protein = "fish"
val starch = "chips"
val drink = "wine"

val complete = List (protein, starch, drink) 
val partly =  List (protein, starch) 

complete.mkString (", ")
partly.mkString (", ")

results in:

res47: String = fish, chips, wine
res48: String = fish, chips

You may even specify a start and end:

scala> partly.mkString ("<<", ", ", ">>")
res49: String = <<fish, chips>>

Upvotes: 14

Related Questions