Scala 如何使元素包含'$';字符作为键,在键后面';什么数字作为列表?
有一个数组,如何使元素包含“$”字符作为键,并在键后面的数字作为列表Scala 如何使元素包含'$';字符作为键,在键后面';什么数字作为列表?,scala,Scala,有一个数组,如何使元素包含“$”字符作为键,并在键后面的数字作为列表 val a = Array("$A", 1234, "$B", 123, 4, 5) 预期: Map("$A"->List(1234),"$B"->List(123,4,5))) thx为所有回答者,以下是我的最终代码: a.toList.tails.collect { case (key: String) :: rest if key.contains('$') => (key, rest.take
val a = Array("$A", 1234, "$B", 123, 4, 5)
预期:
Map("$A"->List(1234),"$B"->List(123,4,5)))
thx为所有回答者,以下是我的最终代码:
a.toList.tails.collect {
case (key: String) :: rest if key.contains('$') => (key, rest.takeWhile(!_.toString.contains('$')))
}.toMap
您可以使用
foldLeft
(假设Array[Any]
作为输入):
需要使用反转
,因为:
(将元素添加到列表的开头)比将元素添加到末尾要快,但是列表[Int]
会以这种方式反转
另一个选项是对的尾部递归调用
注意,Map
不能保证插入顺序(即使对于键,不管它是迭代器),因此不能将其用于累加器(不能从中获取键。最后一个元素):
但是,您可以使用ListMap
,但是键。last
比list.head
(恒定时间)慢(线性时间)
p.S.2请记住,您的a.toList.tails.collect…
版本会重新访问某些元素2-3次:1次是collect跳过整数,1次是takeWhile检测序列结束,因此可能会影响性能。这可以通过简单的折叠实现:
val a = Array("$A", 1234, "$B", 123, 4, 5)
a.foldLeft((Map.empty[String, List[Int]], Option.empty[String])) {
case ((map, _), ele: String) if ele.startsWith("$") =>
(map + (ele -> List[Int]()), Some(ele))
case ((map, Some(lastKey)), ele: Int) =>
(map + (lastKey -> (map(lastKey) :+ ele)), Some(lastKey))
} _1
结果是一个Map($a->List(1234),$B->List(123,4,5))
折叠阵列中的元素。如果元素包含“$”,则创建新列表并保存密钥以供以后使用。在Int
的情况下,将元素添加到lastKey
的列表中。获取结果元组的第一个元素,以除去lastKey
- 首先找到
$
的索引。示例列表((“$A”,0),(“$B”,2))
- 并找到每个
$
的范围<代码>(“$A”,0,2),(“$B”,2,6))
然后用上面的$
范围对数组进行切片
举个例子
val input = Array("$A", 1234, "$B", 123, 4, 5)
val index$Elems = input.zipWithIndex.map {case (elem, index) =>
if (elem.toString.startsWith("$")) elem.toString -> index
} filter(!_.isInstanceOf[BoxedUnit])
val groupElems = index$Elems.zipWithIndex.map {
case (kv: (String, Int), index: Int) if index != index$Elems.length - 1 =>
Tuple3(kv._1, kv._2, index$Elems(index + 1).asInstanceOf[(String, Int)]._2)
case (keyvalue: (String, Int), index) if index == index$Elems.length - 1 =>
Tuple3(keyvalue._1, keyvalue._2, input.length)
} map { elems: (String, Int, Int) =>
Map(elems._1 -> input.slice(elems._2 + 1, elems._3).toList)
}
测验
您尝试了什么?只是为了澄清一下,为什么最初不使用映射(参见我的答案)?@thwieganMap
不保留插入顺序(除了像3个元素这样的小集合),即keys
迭代器实际上是集合
。这就是为什么我总是喜欢List
。有一个解决方法(ListMap),但是它比常规的Map
@thwiegan有开销,所以你不能使用键。last
在裸Map
上(HashMap
)@thwiegan也有键。last
在ListMap
中花费线性时间,谢谢你提供的信息:)相应地更新了我的答案。
val a = Array("$A", 1234, "$B", 123, 4, 5)
a.foldLeft((Map.empty[String, List[Int]], Option.empty[String])) {
case ((map, _), ele: String) if ele.startsWith("$") =>
(map + (ele -> List[Int]()), Some(ele))
case ((map, Some(lastKey)), ele: Int) =>
(map + (lastKey -> (map(lastKey) :+ ele)), Some(lastKey))
} _1
val input = Array("$A", 1234, "$B", 123, 4, 5)
val index$Elems = input.zipWithIndex.map {case (elem, index) =>
if (elem.toString.startsWith("$")) elem.toString -> index
} filter(!_.isInstanceOf[BoxedUnit])
val groupElems = index$Elems.zipWithIndex.map {
case (kv: (String, Int), index: Int) if index != index$Elems.length - 1 =>
Tuple3(kv._1, kv._2, index$Elems(index + 1).asInstanceOf[(String, Int)]._2)
case (keyvalue: (String, Int), index) if index == index$Elems.length - 1 =>
Tuple3(keyvalue._1, keyvalue._2, input.length)
} map { elems: (String, Int, Int) =>
Map(elems._1 -> input.slice(elems._2 + 1, elems._3).toList)
}
groupElems.head("$A") shouldBe List(1234)
groupElems.last("$B") shouldBe List(123, 4, 5)