Preamble
It occurred to me that the status could be seen as having a priority, and if given a sequence of (agent,status)
pairs then the task is to select only the highest priority status for each agent. Unfortunately, status isn't strongly typed with an explicit ordering so defined, but... as it's a string with only two values we can safely use string ordering as having a 1:1 correspondence to the priority.
Both my answers take advantage of two useful facts:
In natural string ordering, "FAIL" < "PASS"
, so:
List("PASS", "FAIL", "PASS").sorted.head = "FAIL"
For two tuples (x,a)
and (x,b)
, (x,a) > (x, b)
if (a > b)
UPDATED REPLY
val solution = l.sorted.reverse.toMap
When converting a Seq[(A,B)]
to a Map[A,B]
via the .toMap
method, each "key" in the original sequence of tuples can only appear in the resulting Map once. As it happens, the conversion uses the last such occurrence.
l.sorted.reverse = List(
(Agent 2,PASS), // <-- Last "Agent 2"
(Agent 1,FAIL), // <-- Last "Agent 1"
(Agent,PASS),
(Agent,PASS),
(Agent,FAIL)) // <-- Last "Agent"
l.sorted.reverse.toMap = Map(
Agent 2 -> PASS,
Agent 1 -> FAIL,
Agent -> FAIL)
ORIGINAL REPLY
Starting with the answer...
val oldSolution = (l groupBy (_._1)) mapValues {_.sorted.head._2}
...and then showing my working :)
//group
l groupBy (_._1) = Map(
Agent 2 -> List((Agent 2,PASS)),
Agent 1 -> List((Agent 1,FAIL)),
Agent -> List((Agent,PASS), (Agent,FAIL), (Agent,PASS))
)
//extract values
(l groupBy (_._1)) mapValues {_.map(_._2)} = Map(
Agent 2 -> List(PASS),
Agent 1 -> List(FAIL),
Agent -> List(PASS, FAIL, PASS))
//sort
(l groupBy (_._1)) mapValues {_.map(_._2).sorted} = Map(
Agent 2 -> List(PASS),
Agent 1 -> List(FAIL),
Agent -> List(FAIL, PASS, PASS))
//head
(l groupBy (_._1)) mapValues {_.map(_._2).sorted.head} = Map(
Agent 2 -> PASS,
Agent 1 -> FAIL,
Agent -> FAIL)
However, you can directly sort the agent -> status
pairs without needing to first extract _2
:
//group & sort
(l groupBy (_._1)) mapValues {_.sorted} = Map(
Agent 2 -> List((Agent 2,PASS)),
Agent 1 -> List((Agent 1,FAIL)),
Agent -> List((Agent,FAIL), (Agent,PASS), (Agent,PASS)))
//extract values
(l groupBy (_._1)) mapValues {_.sorted.head._2} = Map(
Agent 2 -> PASS,
Agent 1 -> FAIL,
Agent -> FAIL)
In either case, feel free to convert back to a List of Pairs if you wish:
l.sorted.reverse.toMap.toList = List(
(Agent 2, PASS),
(Agent 1, FAIL),
(Agent, FAIL))