列表的元素取决于先前的元素
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了列表的元素取决于先前的元素相关的知识,希望对你有一定的参考价值。
假设我有一个递增整数的列表。如果两个连续数字的差小于阈值,那么我们将从0开始以相同的数字对其进行索引。否则,我们将索引增加1。
例如:对于列表(1,2,5,7,8,11,15,16,20)并且阈值= 3,输出将为:(0,0,1,1,1,1,2 ,3、3、4)。
这是我的代码:
val listToGroup = List(1,2,5,7,8,11,15,16,20)
val diff_list = listToGroup.sliding(2,1).map{case List(i, j) => j-i}.toList
val thres = 2
var j=0
val output_ = for(i <- diff_list.indices) yield {
if (diff_list(i) > thres ) {
j += 1
}
j
}
val output = List.concat(List(0), output_)
我是Scala的新手,我觉得列表没有得到有效使用。如何改进此代码?
答案
val listToGroup = List(1, 2, 5, 7, 8, 11, 15, 16, 20)
val thres = 2
listToGroup
.sliding(2)
.scanLeft(0)((a, b) => { if (b.tail.head - b.head > thres) a + 1 else a })
.toList
.tail
您不需要使用可变变量,可以使用scanLeft实现相同的功能。
另一答案
您可以通过使用scanLeft
以获得更惯用的代码来避免使用可变变量:
val output = diff_list.scanLeft(0) { (count, i) =>
if (i > thres) count + 1
else count
}
[您的代码显示了一些在Scala中通常避免使用的构造,但是当来自过程语言时,它们是常见的,例如:for(i <- diff_list.indices) ... diff_list(i)
可以用for(i <- diff_list)
代替。
[除此之外,我认为您的代码有效-您仍然需要遍历列表,并在O(N)
中进行操作。在这里,我无需担心效率,而更多地关注样式和可读性。
我对整个代码在Scala中更自然的看法是:
val listToGroup = List(1,2,5,7,8,11,15,16,20)
val thres = 2
val output = listToGroup.zip(listToGroup.drop(1)).scanLeft(0) { case (count, (i, j)) =>
if (j - i > thres) count + 1
else count
}
我对您代码的调整:
- 我使用
scanLeft
执行结果收集构造 - 我更喜欢
x.zip(x.drop(1))
而不是x.sliding(2, 1)
(构造元组似乎比构造集合更有效)。您也可以使用x.zip(x.tail)
,但是不能处理空的x
- 我避免出现临时结果
diff_list
以上是关于列表的元素取决于先前的元素的主要内容,如果未能解决你的问题,请参考以下文章