代码之家  ›  专栏  ›  技术社区  ›  Ellen Spertus

在scala中转换地图

  •  0
  • Ellen Spertus  · 技术社区  · 7 年前

    我想转换类型的地图 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))}
    
    2 回复  |  直到 7 年前
        1
  •  1
  •   Andrey Tyukin    7 年前
    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)
    

    编辑

    为每个 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) ,但这仍然不是你想要的。

        2
  •  1
  •   Timothy Jones    7 年前

    错误消息告诉您 .map 具有窗体的函数 String => ? 但是你要传递一个 (String, String) .

    (k.concat(":").concat(k), k) 不是功能-我认为你不是故意 k 两次在 concat .

    要创建映射,需要一个带有签名的函数 String => (String, String)

    • vs.map((k.concat(":").concat(k),k)) 传球失误 (字符串,字符串) 映射
    • vs.map((k.concat(":").concat(_),k)) 不正确的传球 (String => String, String) 绘制地图。
    • vs.map(v => (k.concat(":").concat(v), k)) 正确匹配 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 而不是 压扁 :

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

    here 如果你想试试的话。

    推荐文章