Преобразование карты в Скале - PullRequest
0 голосов
/ 30 мая 2018

Я хотел бы преобразовать карту типа String -> List[String] в Scala таким образом, чтобы каждая пара (k, (List v1, v2, ... vn)) ключ-значение приводила к парам {(k:v1, k), (k:v2, k), ... (k:vn, k)}.

Например, я хотел бы преобразовать

scala.collection.immutable.Map[String,List[String]] = Map(A -> List(a1, a2), B -> List(b1))

до

scala.collection.immutable.Map[String,List[String]] = Map(A:a1 -> A, A:a2 -> A, B:b1 -> B)

Я смог частично достичь своей цели, используя [этот ответ] [1]:

scala> val schema = Map("A" -> List("a1", "a2"),  "B" -> List("b1"))
schema: scala.collection.immutable.Map[String,List[String]] = Map(A -> List(a1, a2), B -> List(b1))

scala>  schema flatten {case(k, vs) => vs.map((_, k))}
res1: scala.collection.immutable.Iterable[(String, String)] = List((a1,A), (a2,A), (b1,B))

Когда я пытаюсь предвосхититьИсходный ключ и двоеточие для каждого значения, я получаю сообщение об ошибке:

scala> schema flatten {case(k, vs) => vs.map((k.concat(":").concat(_), k))}
<console>:13: error: type mismatch;
 found   : (String => String, String)
 required: String => ?
       schema flatten {case(k, vs) => vs.map((k.concat(":").concat(_), k))}

Ответы [ 2 ]

0 голосов
/ 30 мая 2018

Сообщение об ошибке сообщает, что .map принимает функцию вида String => ?, но вы передаете ей кортеж (String, String).

(k.concat(":").concat(k), k) не является функцией -также я думаю, что вы не хотели ставить k дважды в concat.

. Для создания карты вам нужна функция с подписью String => (String, String)

  • vs.map((k.concat(":").concat(k),k)) неправильно передает (String, String) на карту
  • vs.map((k.concat(":").concat(_),k)) неправильно передает (String => String, String) на карту.
  • vs.map(v => (k.concat(":").concat(v), k)) правильно соответствует String => (String, String).

Затем мы можем получить:

schema flatten {case(k, vs) => vs.map(v => (k.concat(":").concat(v), k)) }
 //  List((A:a1,A), (A:a2,A), (B:b1,B)) 

Вы можете увидеть этот код в действии здесь .

Однако, как замечает замечательный комментарий Андрея, не рекомендуется использоватьflatten с неявной функцией.Кроме того, вы хотите Map, а не List.По этим двум причинам, я думаю, вы должны использовать flatMap вместо flatten:

schema flatMap {case(k, vs) => vs.map(v => (k.concat(":").concat(v), k)) };
// Map(A:a1 -> A, A:a2 -> A, B:b1 -> B)

См. здесь , если вы хотите попробовать его.

0 голосов
/ 30 мая 2018
  1. В (k.concat(":").concat(k), k) нет _ и нет переменных, поэтому это не литерал функции, но аргумент map должен быть функцией.
  2. Вы не хотитеобъединить k с k в любом случае

Попробуйте это:

schema.flatMap { case (k, vs) => vs.map(v => (k + ":" + v, k)) }

или даже более кратко:

for ((k, vs) <- schema; v <- vs) yield (k + ":" + v, k)

EDIT

Для каждого k выражение k.concat(":").concat(_) является функцией, которая принимает строку s и вычисляет k + ":" + s.

Следовательно, (k.concat(":").concat(_), k) являетсякортеж

  1. Функция x => k.concat(":").concat(x) и
  2. значение k

Таким образом, он имеет тип (String => String, String).Это отличается от String => (String, String), и это все еще не то, что вы хотите.

...