0

In Scala, what is the best way to add an element to a list while making sure that the list always contains latest n elements.

So if list is (1, 2, 3, 4, 5) and n = 5, then adding 6 should result in (2, 3, 4, 5, 6).

One possible way could be:

list = list ::: List(6)
list = list.takeRight(5)

Are there any better ways? Also, is there a better data-structure for maintaining such frequently changing collection?

Ihor Kaharlichenko
  • 5,944
  • 1
  • 26
  • 32
Tarun Kumar
  • 5,150
  • 6
  • 26
  • 30
  • possible duplicate of [Best practice for shifting a sequence in a circular manner](http://stackoverflow.com/questions/8876769/best-practice-for-shifting-a-sequence-in-a-circular-manner) – Ihor Kaharlichenko Sep 30 '15 at 11:04

1 Answers1

1

It sounds like a fixed size Circular Buffer would satisfy your need. I think apache commons provides some implementation.

A solution in scala using List could be:

scala> def dropHeadAndAddToList[T](obj: T, list: List[T]):List[T] = {
          list.drop(1) :+ obj
       }

       dropHeadAndAddToList: [T](obj: T, list: List[T])List[T]

scala> val a = List(1,2,3,4,5)
a: List[Int] = List(1, 2, 3, 4, 5)

scala> dropHeadAndAddToList(6, a)
res0: List[Int] = List(2, 3, 4, 5, 6)
rahilb
  • 726
  • 3
  • 15
  • Imo, "addToList" doesn't sound like a good name for a function, which removes element from a list :) Actually just "myList.drop(1) :+ 6" looks not so bad. – psisoyev Sep 30 '15 at 11:00
  • You're right, naming things is hard and my answer was lazy in this regard! I'll edit it to a better name :) – rahilb Sep 30 '15 at 11:04
  • how does list.drop(1) compare with list.takeRight(n) performance wise? – Tarun Kumar Sep 30 '15 at 12:30
  • scala> val time = System.currentTimeMillis; for (i <- 1 to 10000000) { list.takeRight(4) }; println(System.currentTimeMillis - time) 122 time: Long = 1443616699385 scala> val time = System.currentTimeMillis; for (i <- 1 to 10000000) { list.drop(1) }; println(System.currentTimeMillis - time) 91 time: Long = 1443616709615 – Tarun Kumar Sep 30 '15 at 12:39
  • 1
    @TarunKumar microbenchmarking in the way you have shown is flawed, the recommended approach is to use [jmh](http://openjdk.java.net/projects/code-tools/jmh/). Even still, [jmh has it's own flaws](http://bad-concurrency.blogspot.co.uk/2014/12/the-uncanny-valley-of-l3-cache.html), so I would be wary of prematurely optimising such a (presumably) small part of the system, based on System.nanoTime calls in the repl. – rahilb Sep 30 '15 at 13:39