How to subtract two consecutive element in a list in Scala?

你说的曾经没有我的故事 提交于 2021-02-10 04:13:49

问题


I would like to subtract two consecutive element in a list with numbers in Scala.

For example : I have this list :

val sortedList = List(4,5,6)

I would like to have an output list like diffList =(1, 1) where 5-4 = 1 and 6-5 = 1.

I tried the following code:

var sortedList = List[Int]()
var diffList = List[Int]()

for (i <- 0 to (sortedList.length - 1) ;j <- i + 1 to sortedList.length - 1) 
{
    val diff = (sortedList(j) - sortedList(i))
    diffList = diffList :+ diff
}

I have the following result for diffList =(1, 2, 1) but I want diffList = (1,1).

It's because of the for loop. it does not iterate over the two variables (i and j) at once.


回答1:


You do not mutability nor imperative programming to solve this problem, functional programming got you covered.

def consecutiveDifferences(data: List[Int]): List[Int] =
  if (data.isEmpty) List.empty
  else data.lazyZip(data.tail).map {
    case (x, y) => y - x
 }

As I always say, the Scaladoc is your friend.
(Also, as an advice, the best way to learn functional programming is to forbid yourself from mutability)




回答2:


You can use the sliding method, which according to the docs:

/** Groups elements in fixed size blocks by passing a "sliding window"
 *  over them (as opposed to partitioning them, as is done in `grouped`.)
 *
 *  An empty collection returns an empty iterator, and a non-empty
 *  collection containing fewer elements than the window size returns
 *  an iterator that will produce the original collection as its only
 *  element.
 *  @see [[scala.collection.Iterator]], method `sliding`
 *
 *  @param size the number of elements per group
 *  @return An iterator producing ${coll}s of size `size`, except for a
 *          non-empty collection with less than `size` elements, which
 *          returns an iterator that produces the source collection itself
 *          as its only element.
 *  @example `List().sliding(2) = empty iterator`
 *  @example `List(1).sliding(2) = Iterator(List(1))`
 *  @example `List(1, 2).sliding(2) = Iterator(List(1, 2))`
 *  @example `List(1, 2, 3).sliding(2) = Iterator(List(1, 2), List(2, 3))`
 */

Then, solving your query is pretty straight forward:

diffList = sortedList.sliding(2).collect {
  case Seq(a, b) =>
    b - a
}.toList

Which results in List(1,1)

Code run at Scastie.




回答3:


for(i <- 0 until (sortedList.size - 1)) yield sortedList(i + 1) - sortedList(i)

yield Vector(1,1) which can be converted to list with toList

That's can be also achieved with the following function:

  val sortedList = List(4,5,7)
  @tailrec
  def findDiffs(xs: List[Int])(seed: List[Int]): List[Int] = {
    if(xs.isEmpty || xs.size == 1) seed.reverse
    else {
      val currDiff = xs(1) - xs(0)
      findDiffs(xs.tail)(currDiff :: seed)
    }
  }
  val res = findDiffs(sortedList)(Nil)
  println(res)

Or just easily with zip:

sortedList.tail zip sortedList map { case (x,y) => x - y } 

Note: will throw UnsupportedOperationException exception on empty sortedList, thus:

sortedList match {                        
  case Nil => List.empty                  
  case list @ _ :: tail => list zip tail  
}                                         

and then .map { case (x, y) => x - y }

Or use .drop(1) instead of tail




回答4:


Sliding (see answer by @Tomer Shetah) over a list delivers an iterator, which may prove convenient for very large collections to avoid/reduce the amount of intermediate structures in the processing. Another approach includes the zipping of the list with itself shifted by one (see answers by @Luis Miguel Mejía Suárez and @Zvi Mints); in this regard another approach to shifting and then zipping is by dropping the first element as in

xs.drop(1) zip xs map {case(a,b) => b-a}

This can be generalised by dropping any number n so that we subtract the first and the n-th elements, then the second and the n+1-th elements, and so forth.



来源:https://stackoverflow.com/questions/65972252/how-to-subtract-two-consecutive-element-in-a-list-in-scala

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!