2012-08-14 106 views
1

我有以下结果地图类型Map[Long,Map[String,String]]。我想将地图转换为List[Seq[Long,String]]迭代和过滤斯卡拉地图

下面的代码做这口井:

val test = for((time, m) <- ret) yield for((k, v) <- m) yield Seq(time, v) 

的问题是,我其实只想包括Seq(time, v)其中v是独一无二的。例如,目前我得到以下值:

[[ 
     1344969305196000, 
     "Ry7H5_client" 
    ], 
    [ 
     1344969777610000, 
     "Ry7H5_client" 
    ], 
    [ 
     1344965964890000, 
     "SOCKET/f6KGcMSVi7" 
    ], 
    [ 
     1344969919131000, 
     "Ry7H5_client" 
    ]] 

我想只在结果集中包含“Ry7H5_client”一次。什么是解决这个问题的最好方法?

+0

你如何确定你的例子中包含3个“Ry7H5_client”中的哪一个?它应该是第一个例子吗? – 2012-08-14 19:32:09

+0

是的,第一次会很好 – chiappone 2012-08-14 19:32:50

+0

请注意,“第一次”在这里并不意味着任何东西(除非你按时间排序),因为地图没有定义的迭代次序。 – 2012-08-14 19:43:12

回答

2

您可以确定按键与某物删除像

val res = Map(1 -> 2, 3 -> 2, 4 -> 1) 

val keysToDelete = res.groupBy(_._2).collect { case (_, m) if m.size > 1 => m.keys }.flatten 
// keysToDelete: scala.collection.immutable.Iterable[Int] = List(1, 3) 

val resultMap = res -- keysToDelete 
// resultMap: scala.collection.immutable.Map[Int,Int] = Map(4 -> 1) 

编辑:

来收集包含短语所有值的键,你可以做

Map(1 -> "FOO_SOCKET_BAR", 2 -> "FOO_BAR").collect { case (key,value) if value.contains("SOCKET") => key } 

和为了更高效,你也可以在这里使用编译正则表达式:

val regex = ".*SOCKET.*".r 
Map(1 -> "FOO_SOCKET_BAR", 2 -> "FOO_BAR").collect { case (key,regex()) => key } 
+0

这很酷。另一个问题是,如果我想删除包含特定单词的值,该怎么办?说我的例子,我不想包含具有“SOCKET”的值的条目? – chiappone 2012-08-14 19:44:21

+0

编辑我的帖子回答你的问题 – drexin 2012-08-14 20:27:17

0

只是GROUPBY的字符串,然后映射到各组的头:

scala> val list = List((1344969305196000L, "Ry7H5_client"), (1344969777610000L, 
"Ry7H5_client"), (1344965964890000L,"SOCKET/f6KGcMSVi7"), (1344969919131000L, "R 
y7H5_client")) 
list: List[(Long, java.lang.String)] = List((1344969305196000,Ry7H5_client), 
(1344969777610000,Ry7H5_client), (1344965964890000,SOCKET/f6KGcMSVi7), 
(1344969919131000,Ry7H5_client)) 

scala> list.groupBy(x => x._2).map((e) => e._2.head).toList 
res0: List[(Long, java.lang.String)] = List((1344965964890000,SOCKET/f6KGcMSVi7), 
(1344969305196000,Ry7H5_client)) 
2

您可以使用多台发电机您的-理解(如果可能被用来为好):

val test = (for { 
    (time, m) <- ret 
    (k,v) <- m 
    if v == "Ry7H5_client" 
} yield Seq(time, v)).toList 
+0

是的我试过了,问题是它然后返回一个空数组,打破返回签名类型 – chiappone 2012-08-14 20:12:33

+0

好吧,你可以用somehese包围表达式并在最后调用toList。我编辑了这个。 – 2012-08-15 05:46:23

0

这个怎么样

object SO extends App { 

    val ret = Map(
    1344969305196000L -> Map("a" -> "Ry7H5_client"), 
    1344969777610000L -> Map("a" -> "Ry7H5_client"), 
    1344965964890000L -> Map("a" -> "SOCKET/f6KGcMSVi7"), 
    1344969919131000L -> Map("a" -> "Ry7H5_client")) 

    val test2 = for { 
    (m, time) <- ret.map(_.swap) 
    (k, v) <- m 
    } yield Seq(time, v) 

    println(test2) 
} 

给出名单(名单(1344969919131000,Ry7H5_client),表(1344965964890000,SOCKET/f6KGcMSVi7))

ps。 Map中的“a”只是为了使这些类型与您原来的问题相匹配,看起来并不重要。