1
\$\begingroup\$

New Scala dev here. Is there a more idiomatic or efficient way to accomplish this in Scala?

Given a list of the following strings, I need to obtain the unique 'main parts' once any parts including and after a "-" have been removed.

The output should be a list of sorted strings. Also note both ";" and "," have been used as separators.

Input:

val data: List[String] = List(
  "W22; O21; B112-WX00BK; G211; B112-WI00BK; G11",
  "W22; K122l; B112-WI00BK; O21; B112-WX00BK; G211",
  "W21, V32",
  "W21, N722",
  "S133-VU3150; S133-SU3150; R22-VK3150; R123-VH3"
)   

Desired Output:

List(
    B112 G11 G211 O21 W22,
    B112 G211 K122l O21 W22,
    V32 W21,
    N722 W21,
    R123 R22 S133
)

My solution:

def process(input: String): String =
    input.split(" ").map(word => {
        if (word contains "-")
            word.take(word.indexOf("-"))
        else word
        .replace(";", "").replace(",","")}).toSet.toList.sorted.mkString(" ")

val result: List[String] = data.map(process(_))
\$\endgroup\$
2
  • \$\begingroup\$ Can you add some more context about why you're doing this? It'd be very helpful. \$\endgroup\$
    – user
    Jul 25, 2021 at 23:09
  • 2
    \$\begingroup\$ data.map(process) is sufficient. \$\endgroup\$
    – jwvh
    Jul 28, 2021 at 3:53

2 Answers 2

2
\$\begingroup\$

First of all, the formatting could be a bit better. It's odd to have the first .replace at the same indentation level as else, and you can call map using curly braces if you want a function with multiple statements/expressions instead of making the function result a block. You don't actually need curly braces, but I'd say they're used for multi-line functions more often than are parentheses.

def process(input: String): String =
  input
    .split(" ")
    .map { word =>
      if (word contains "-")
        word.take(word.indexOf("-"))
      else
        word
          .replace(";", "")
          .replace(",", "")
    }
    .toSet
    .toList
    .sorted
    .mkString(" ")

Using .toSet.toList is unnecessary - you can use .distinct instead. It might be a good idea to make a View after splitting the string to avoid making too many intermediate collections. You'll have to convert it to a Seq before sorting it, though, since sorted isn't defined for views.

You can also replace ; and , using the regex [;,]. You'll need to use replaceAll instead of replace to use regex, though. However, why not include these two when you're splitting? If you do that, each word would only have to be mapped by word => word.takeWhile(_ != '-'), or _.takeWhile(_ != '-').

Doing that, we get the following:

def process(input: String): String =
  input
    .split("[;,] ")
    .view
    .map(_.takeWhile(_ != '-'))
    .distinct
    .toSeq
    .sorted
    .mkString(" ")

This feels like it should do fewer operations than your original, although I'm not sure if _.takeWhile(_ != '-') will be faster than the regex from vvotan's answer.

If your data really is that small, though, efficiency shouldn't matter much. Could you provide some more information on what you're trying to do? Your description doesn't help much, and names such as data, result, input, and process are very generic and won't help readers.

\$\endgroup\$
1
  • \$\begingroup\$ Thank you for the explanation of each change. \$\endgroup\$ Jul 29, 2021 at 16:13
1
\$\begingroup\$

Maybe regex to the rescue?

val formatRegexp = "([A-Za-z0-9]+)(-.*)?[;,]?".r
data.map(_.split(" ").map({
  case formatRegexp(value, _*) => value
  case _ => ""
}).sorted.distinct.mkString(" ") )
\$\endgroup\$
5
  • 1
    \$\begingroup\$ Nice approach. You can use {} instead of ({}) for the call to map. \$\endgroup\$
    – user
    Jul 24, 2021 at 22:54
  • \$\begingroup\$ I think you can use formatRegexp.findAllIn(_).group(1) inside the second call to map to make it a little more concise (and hopefully more readable). \$\endgroup\$
    – user
    Jul 25, 2021 at 23:06
  • 1
    \$\begingroup\$ @user, I think it depends on your personal style. In my opinion, having an explicit way of handling non-matching entries makes it a little bit more maintainable. \$\endgroup\$
    – vvotan
    Jul 26, 2021 at 10:55
  • 1
    \$\begingroup\$ This answer is a little lightweight for a real Code Review. \$\endgroup\$
    – jwvh
    Jul 26, 2021 at 18:20
  • \$\begingroup\$ @vvotan, I really love this solution, but had to choose the other answer. Agree with jwvh, this is a little lightweight. \$\endgroup\$ Jul 29, 2021 at 16:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.