Home > Software design >  No implicits found for parameter ev: Any <:< (T_, U_)
No implicits found for parameter ev: Any <:< (T_, U_)

Time:07-12

I'm trying to create a map based on conditions. Here's the general workflow in pseudocode:


def createMyMap(input: String): Map[String, String] = {
  val stringArray = input.split(",")

  stringArray.map(element => {
    if (condition) {
      newKey -> newVal
    }
  }).toMap
}

and I see two compile errors:

  1. No implicits found for parameter ev: Any <:< (T_, U_) in the toMap call
  2. For the method createMyMap
Type mismatch.
Required: scala.Predef.Map [String, String]
Found: scala.collection.immutable.Map[Nothing, Nothing]

This makes sense since the compiler doesn't know how to create the map if the condition isn't fulfilled. For example, if I add this in the method:

if (condition) {
  newKey -> new Val
} else {
  null
}

then it'll compile. I'm just not too sure how to approach the else - how do I avoid this kind of problem? I'm running into this because I only want to create a map entry if a condition is fulfilled.

CodePudding user response:

You have a few good options that I'll summarize from the comments:

  1. filter map toMap
// stringArray: Traversable[String]
// condition: String => Boolean
// transform: String => (String, String)

val result: Map[String, String] = stringArray
  .filter(condition)
  .map(transform)
  .toMap
  1. map flatten toMap
val result: Map[String, String] = stringArray
  .map { k =>
    if (condition(k)) Some(transform(k))
    else None
  }
  .flatten
  .toMap
  1. flatMap toMap
val result: Map[String, String] = stringArray
  .flatMap { k =>
    if (condition(k)) Some(transform(k))
    else None
  }
  .toMap
  1. collect toMap
val result: Map[String, String] = stringArray
  .collect {
    case k if condition(s) => transform(k)
  }
  .toMap

See documentation.

In short, methods 3 and 4 are especially clean (although all are good IMO). However, the one that is semantically the most readable IMO is 4, which uses collect (with option 1 being a close second).

CodePudding user response:

It's not clear how newKey and newVal are derived, but here is the template code using collect

def createMyMap(input: String): Map[String, String] =
  input.split(",").collect {
    case s if <condition> =>
      newKey -> newVal
  }.to(Map)

e.g.

def createMyMap(input: String): Map[String, String] =
  input.split(",").collect {
    case s if s.contains('.') =>
      s -> "data"
  }.to(Map)
  • Related