Preamble
It occurred to me that status can be considered as having priority, and if a sequence of pairs (agent,status) , then the task is to select only the highest priority status for each agent. Unfortunately, the status is not strongly typed with explicit ordering defined in this way, but ... since it is a string with only two values, we can safely use string ordering as having a 1: 1 priority.
My answers use two useful facts:
In the natural ordering of strings is "FAIL" < "PASS" , therefore:
List("PASS", "FAIL", "PASS").sorted.head = "FAIL"
For two tuples (x,a) and (x,b) , (x,a) > (x, b) if (a > b)
UPDATED ANSWER
val solution = l.sorted.reverse.toMap
When converting a Seq[(A,B)] to Map[A,B] using the .toMap method .toMap each "key" in the original sequence of tuples can appear only once in the resulting map. Since this happens, the conversion uses the last such event.
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 RESPONSE
Starting from the answer ...
val oldSolution = (l groupBy (_._1)) mapValues {_.sorted.head._2}
... and then showing my work :)
//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 sort the agent -> status pairs directly without having 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 any case, feel free to convert back to the list of pairs if you want:
l.sorted.reverse.toMap.toList = List( (Agent 2, PASS), (Agent 1, FAIL), (Agent, FAIL))