scala - 列出其元素依赖于之前的元素
问题描述
假设我有一个递增整数的列表。如果 2 个连续数字的差值小于阈值,则我们按相同的数字对它们进行索引,从 0 开始。否则,我们将索引增加 1。
例如:对于列表 (1,2,5,7,8,11,15,16,20) 并且阈值 = 3,输出将是:(0, 0, 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 的新手,我觉得这个列表没有得到有效使用。如何改进此代码?
解决方案
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
推荐阅读
- python-3.x - 有人可以解释这个 Python 输入/输出代码吗
- c - 克隆:不允许使用 C 进行操作
- java - 如何从我的类路径运行 Liquibase changeLogFile
- vb.net - VB.NET 2019 - 在类库项目中使用实体框架创建项目
- javascript - 通过单击按钮获取特定的 HTML 页面?(HTML/JavaScript)
- vb6-migration - 如何显示在 Windows10 上运行的 VB6 程序的等待光标
- javascript - 有没有办法使用 github 的 API 获取图像?
- python - 具有固定长度和一些字符的 Python 随机字符串/文本/代码生成器
- google-calendar-recurring-events - 谷歌日历重复如果一个月的最后一天不是工作日,那么下个月的第一个工作日
- javascript - 如何将此 cURL 请求转换为 UrlFetchApp?