列表的元素取决于先前的元素

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

以上是关于列表的元素取决于先前的元素的主要内容,如果未能解决你的问题,请参考以下文章

13 个非常有用的 Python 代码片段

是否可以交换集合中的两个元素?

Python代码阅读(第13篇):检测列表中的元素是否都一样

从另一个片段中的目录更新片段中的列表视图元素

HTML 样式列表元素,其字体大小取决于元素

从流输入中解析没有根元素的 XML 片段列表