我想在Scala中转换String -> List[String]
类型的地图,这样每个(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))}
答案 0 :(得分:1)
_
中没有(k.concat(":").concat(k), k)
且没有变量,因此它不是函数文字,但map
的参数必须是函数。k
与k
联系起来试试这个:
schema.flatMap { case (k, vs) => vs.map(v => (k + ":" + v, k)) }
或者更简洁:
for ((k, vs) <- schema; v <- vs) yield (k + ":" + v, k)
修改强>
对于每个k
,表达式k.concat(":").concat(_)
是一个函数,它接受字符串s
并计算k + ":" + s
。
因此,(k.concat(":").concat(_), k)
是
x => k.concat(":").concat(x)
和k
因此它的类型为(String => String, String)
。这与String => (String, String)
不同,而且仍然不是您想要的。
答案 1 :(得分:1)
错误消息告诉您.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))
您可以在行动here中看到此代码。
然而,正如安德烈的优秀评论所指出的,将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)
如果您想尝试一下,请参阅here。