chiappone
chiappone

Reputation: 2908

Iteration and filtering of a Scala Map

I have the following result Map that has the type Map[Long,Map[String,String]]. I would like to convert the Map to a List[Seq[Long,String]].

The following code does this well:

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

The issue is I actually only want to include the Seq(time, v) where v is unique. For example, currently I get the following values:

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

I would like to only include the "Ry7H5_client" once in my result set. What would be the best way of going about this?

Upvotes: 1

Views: 272

Answers (4)

drexin
drexin

Reputation: 24413

You can determine the keys to delete with sth like

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)

edit:

to collect the keys for all values, that contain a phrase you can do

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

and to be more efficient, you could also use a compiled regex here:

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

Upvotes: 2

tgr
tgr

Reputation: 3608

You can use multiple generators in your for-comprehension (if might be used as well):

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

Upvotes: 2

Emil L
Emil L

Reputation: 21081

Just groupBy the Strings and then map to the head of each group:

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))

Upvotes: 0

Channing Walton
Channing Walton

Reputation: 4007

How about this

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)
}

Gives List(List(1344969919131000, Ry7H5_client), List(1344965964890000, SOCKET/f6KGcMSVi7))

ps. the "a" in the Map is just to make the types match your original problem, it looks like its not important.

Upvotes: 0

Related Questions