Возможно, это решит проблему:
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.