Частично отфильтруйте карту, чтобы получить ключ: Scala - PullRequest
0 голосов
/ 01 мая 2020

У меня есть карта:

val mapTest = Map("Haley" -> Map("Deran" -> 0.4, "Mike" -> 0.3), "Jack" -> Map("Deran" -> 0.3, "Mike" -> 0.3))

Я хочу получить ключ на основе значения. Учитывая значение "Deran"-> 0.4 я должен получить "Haley".

Я пытался использовать это:

mapTest.filter(_._2 == Map("Deran" -> 0.4))

, но это не работает, так как фильтр выбирает все значения за один раз. Это первый вопрос. Мой второй вопрос: что, если два ключа подтверждают, что предикаты, такие как случай для "Jack" и "Haley" для "Mike"

Ответы [ 2 ]

4 голосов
/ 01 мая 2020

Может быть, вы хотите что-то вроде этого:

val toSearch = List("Deran - > 0.4," Mike" -> 0.3)
mapTest.collectFirst {
  case (key, values) if (toSearch.forall { case (k, v) => values.get(k).contains(v) }) => key
}
2 голосов
/ 01 мая 2020

Возможно, это решит проблему:

def filter[K, NK, NV](m: Map[K, Map[NK, NV]])(p: ((NK, NV)) => Boolean): Vector[K] =
  m.view.collect { case (k, v) if v.exists(p) => k }.toVector

Где NK - это обобщенный тип c для n ested-ключа и NV обобщенный c тип для n ested value.

Это работает следующим образом со следующими входами и выходами

val in1: (String, Double) = "Deran" -> 0.4
val out1: Vector[String] = Vector("Haley")

val in2: (String, Double) = "Mike" -> 0.3
val out2: Vector[String] = Vector("Haley", "Jack")

assert(filter(mapTest)(_ == in1) == out1)
assert(filter(mapTest)(_ == in2) == out2)

Вы можете поиграться с этим кодом здесь, в Scast ie.

Используя предикат, вы можете быть очень обобщенными c, но учтите, что сложность возрастает пропорционально размеру как карты, так и вложенных карт, содержащихся в ней.

Если вы можете быть менее универсальным c и просто проверить на равенство, вы можете отбросить предикат и использовать его в своих интересах, чтобы выполнить вложенную проверку в постоянное время:

def filter[K, NK, NV](m: Map[K, Map[NK, NV]])(p: (NK, NV)): Vector[K] =
  m.view.collect { case (k, v) if v.get(p._1).contains(p._2) => k }.toVector

assert(filter(mapTest)(in1) == out1)
assert(filter(mapTest)(in2) == out2)

Этот вариант также доступно здесь на Scast ie.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...