有一个数组,如何使元素包含'$'字符作为键,并在键的数字后面作为List
val a = Array("$A", 1234, "$B", 123, 4, 5)
Run Code Online (Sandbox Code Playgroud)
预期:
Map("$A"->List(1234),"$B"->List(123,4,5)))
Run Code Online (Sandbox Code Playgroud)
所有回答者的thx,如下是我的最终代码:
a.toList.tails.collect {
case (key: String) :: rest if key.contains('$') => (key, rest.takeWhile(!_.toString.contains('$')))
}.toMap
Run Code Online (Sandbox Code Playgroud)
你可以这样做foldLeft(假设Array[Any]作为输入):
a.foldLeft(List.empty[(String, List[Int])]){
case (acc, el: String) if el.head == '$' =>
(el -> List.empty[Int]) :: acc
case (acc, el) =>
val updatedHead = acc.head._1 -> (Integer.parseInt(el.toString) :: acc.head._2)
updatedHead :: acc.tail
}.toMap.mapValues(_.reverse)
Run Code Online (Sandbox Code Playgroud)
reverse需要因为::(将元素添加到List的开头)比将元素添加到结尾更快,但是以List[Int]这种方式反转.
另一种选择是尾递归调用span.
PS小心,Map不保证插入顺序(即使是键,无论它是迭代器),所以你不能将它用于累加器(你不能从中获取keys.last元素):
scala> (1 to 10).toList.foldLeft(Map.empty[Int, Int]){case (acc, x) => acc + (x -> x)}.keys.toList
res23: List[Int] = List(5, 10, 1, 6, 9, 2, 7, 3, 8, 4)
Run Code Online (Sandbox Code Playgroud)
但是,您可以使用ListMap,但keys.last比list.head(恒定时间)慢(线性时间).
PS2请记住,您的a.toList.tails.collect...版本会重新访问某些元素2-3次:当collect跳过整数时,1次额外的时间,当takeWhile检测到序列结束时另外1次,因此可能会影响性能.