我有一个已排序的元组列表(按最后一个元素,即行号排序)
val x = List(
("taskENTER_CRITICAL", 1443),
("taskEXIT_CRITICAL", 1492),
("taskEXIT_CRITICAL", 1510),
("taskEXIT_CRITICAL", 1528),
("taskENTER_CRITICAL", 1551),
("taskEXIT_CRITICAL", 1555),
("taskENTER_CRITICAL", 1602),
("taskEXIT_CRITICAL", 1614)
)
我需要将其转换为
("taskENTER_CRITICAL", 1443),
("taskEXIT_CRITICAL", 1528),
("taskENTER_CRITICAL", 1551),
("taskEXIT_CRITICAL", 1555),
("taskENTER_CRITICAL", 1602),
("taskEXIT_CRITICAL", 1614)
根据迭代列表的条件删除两个元素,并且仅在遇到列表中的下一个ENTER时才选择上一个EXIT
最后需要将其转变为牛肚
("CS", 1443, 1528)
("CS", 1551, 1555)
("CS", 1602, 1614)
答案 0 :(得分:2)
这是一种使用foldLeft
和Tuple型累加器的方法,该累加器将当前字符串元素移到下一次迭代中以进行相等性检查,然后使用grouped
进行最终转换:
val list = List(
("taskENTER_CRITICAL", 1443),
("taskEXIT_CRITICAL", 1492),
("taskEXIT_CRITICAL", 1510),
("taskEXIT_CRITICAL", 1528),
("taskENTER_CRITICAL", 1551),
("taskEXIT_CRITICAL", 1555),
("taskENTER_CRITICAL", 1602),
("taskEXIT_CRITICAL", 1614)
)
val list2 = list.foldLeft( (List[(String, Int)](), "") ){
case ((l, sp), (s, i)) => s match {
case "taskENTER_CRITICAL" => ((s, i) :: l, s)
case "taskEXIT_CRITICAL" if s == sp => ((s, i) :: l.tail, s)
case _ => ((s, i) :: l, s)
}
}._1.reverse
// list2: List[(String, Int)] = List(
// (taskENTER_CRITICAL,1443), (taskEXIT_CRITICAL,1528),
// (taskENTER_CRITICAL,1551), (taskEXIT_CRITICAL,1555),
// (taskENTER_CRITICAL,1602), (taskEXIT_CRITICAL,1614)
// )
list2.grouped(2).collect{ case List(a, b) => ("CS", a._2, b._2) }.toList
// res2: List[(String, Int, Int)] = List((CS,1443,1528), (CS,1551,1555), (CS,1602,1614))
请注意,foldLeft
之后需要反转列表元素,因为列表是按照相反的顺序与::
和tail
组合在一起的,以实现大规模的性能。
答案 1 :(得分:1)
.foldLeft
是主要的累加器模式。您需要知道在现有列表的顶部创建新列表,而不会使现有列表(:+
)发生变化,还需要使用.copy
val data = List(
("taskENTER_CRITICAL", 1443),
("taskEXIT_CRITICAL", 1492),
("taskEXIT_CRITICAL", 1510),
("taskEXIT_CRITICAL", 1528),
("taskENTER_CRITICAL", 1551),
("taskEXIT_CRITICAL", 1555),
("taskENTER_CRITICAL", 1602),
("taskEXIT_CRITICAL", 1614)
)
val enterExits =
data.foldLeft((List.empty[(String, Int)], Option.empty[(String, Int)])) {
case ((state, previousSignal), signal) =>
if (previousSignal.exists(_._1.contains("EXIT")) && signal._1.contains("EXIT")) {
(state.dropRight(1) :+ signal, Some(signal))
} else {
(state :+ signal, Some(signal))
}
}
val triple =
enterExits._1
.foldLeft(
(List.empty[(String, Int, Int)], Option.empty[(String, Int, Int)])) {
case ((state, accSignal), signal) =>
if (signal._1.contains("ENTER")) {
(state, Some(("CS", signal._2, 0)))
} else {
val enterExt = accSignal.map(elem => elem.copy(_3 = signal._2))
(state :+ enterExt.get, Option.empty)
}
}._1
triple.foreach { ee =>
println(ee)
}
输出:
(CS,1443,1528)
(CS,1551,1555)
(CS,1602,1614)
注意:上面的答案假设每个Exit
总是有相等的Enter
。
在https://scastie.scala-lang.org/prayagupd/3670tsL0Qf683QFAQ9nLIQ
上运行代码