我想通过每当元素重复如下所示时就中断,将元素列表转换为列表列表
输入:
List(1, 2, 3, 1, 2, 1, 3, 1, 2, 3)
输出:
List[List[Integer]] = List(List(1, 2, 3), List(1, 2), List(1, 3), List(1, 2, 3))
这是我尝试过的:
val tokens = List(1,2,3,1,2,1,3,1,2,3)
val group = new ListBuffer[List[Integer]]()
val nextGroup = new ListBuffer[Integer]()
val nextTokens = new ListBuffer[Integer]()
for (t <- tokens) {
if (nextTokens.contains(t)) {
group += nextGroup.toList
nextGroup.clear()
nextTokens.clear()
}
nextGroup += t
nextTokens += t
}
group += nextGroup.toList
group.toList
我正在寻找一种更好的方法来使用map / foldLeft ...函数而不使用ListBuffer。
谢谢。
答案 0 :(得分:0)
这是使用foldLeft
tokens
.drop(1)
.foldLeft(List(tokens.take(1))) { case (res, token) =>
if (res.head.contains(token)) {
List(token) +: res
} else {
(res.head :+ token) +: res.tail
}
}
.reverse
使用drop
和take
可以确保它在空白列表上有效。反向生成结果意味着最新的List
总是首当其冲,并且对于长列表来说也是有效的。
为了完整起见,这是一个执行相同功能的递归函数:
def groupDistinct[T](tokens: List[T]): List[List[T]] = {
@tailrec
def loop(token: List[T], cur: List[T], res: List[List[T]]): List[List[T]] =
token match {
case Nil =>
res :+ cur
case head :: tail =>
if (cur.contains(head)) {
loop(tail, List(head), res :+ cur)
} else {
loop(tail, cur :+ head, res)
}
}
loop(tokens, Nil, Nil)
}
答案 1 :(得分:0)
使用下面提供的解决方案,我提出了以下解决方案
https://stackoverflow.com/a/52976957/1696418
mySeq.foldLeft(List.empty[List[Int]]) {
case (acc, i) if acc.isEmpty => List(List(i))
case (acc, i) if acc.last.contains(i) => acc :+ List(i)
case (acc, i) => acc.init :+ (acc.last :+ i)
}
答案 2 :(得分:0)
这是一个非常直接的解决方案,它在跟踪两个累加器数组的同时使用q
:一个用于最终结果,一个用于当前考虑的令牌子列表。最后,我们将结果数组与最后一个子列表结合起来。
int main(void) {
int m=44;
int *p = &m;
int* q = p-1;
printf("%p\n",(void*)q); /* this is valid */
//printf("%d \n",*q); /* this cause seg fault */
return 0;
}
请注意,这并不是计算效率最高的解决方案,因为对于每次迭代,我们正在使用foldLeft
来检查正在考虑的整个子列表。如果您希望提高效率,则可以(取决于您的数据)考虑一种使用哈希映射或类似数据结构的方法来代替快速重复检查。