I'm currently trying to extract neighbours in a List who differ by 1. For example if I had my List like this:
List(1,2,3,7,8,10,13,14)
//By extracting I want to get:
List(
List(1,2,3),
List(7,8),
List(10),
List(13,14)
)
I've tried it myself by doing foldLeft, I felt like I was close but yet so far. Can anyone help me? Any suggestions? ^^
Thank you so much! :)
Here is a solution using foldRight
:
val oldList = List(1, 2, 3, 7, 8, 10, 13, 14)
val newList = oldList.foldRight[List[List[Int]]](Nil)((a, b) => b match {
case (bh @ bhh :: _) :: bt if (bhh - a == 1) => (a :: bh) :: bt
case _ => (a :: Nil) :: b
})
So we iterate the entries backwards and either prepend to the existing head list or add a new head list depending on whether the difference is one:
Nil
(14, ...) => (14 :: Nil) :: Nil
(13, ...) => (13 :: 14 :: Nil) :: Nil
(10, ...) => (10 :: Nil) :: (13 :: 14 :: Nil) :: Nil
...
I haven't used Scala for a while so this might not be the best solution, but I hope you get the idea.
Consecutive integers will increment in line with the list index, thus we can subtract the index and they'll form groups of the same number
val li = List(1, 2, 3, 7, 8, 10, 13, 14)
val groups = li.zipWithIndex.groupBy({case (e, i) => e - i}) // group numbers
groups.values.toList.map(_.map(_._1)) // drop indices and grouping keys
Note: these will lose the ordering of unordered initial list. For your case, you can reorder with .sortBy(_.head)
//First Part: Separates the list into ordered pairs with tail - head == 1
val ls = List(1,2,3,7,8,10,13,14)
val lb: ListBuffer[List[Int]] = new ListBuffer[List[Int]]()
for (List(left,right) <- ls.sorted.sliding(2)) {
if (right - left == 1) {
lb += List(left, right)
}else {
if(!lb.flatten.toList.contains(left)) lb += List(left)
}
}
println(lb.toList)
//Second Part: Merges ordered pairs (x1, y1) and (x2, y2) when y1 == y2
val finalLb: ListBuffer[List[Int]] = new ListBuffer[List[Int]]()
for (List(left,right) <- lb.toList.sliding(2)) {
if(left.tail.contains(right.head)) {
finalLb += (left ++ right).distinct
}else{
finalLb += right
}
}
println(finalLb.toList)
Outputs
First Part: List(List(1, 2), List(2, 3), List(7, 8), List(10), List(13, 14))
Second Part: List(List(1, 2, 3), List(7, 8), List(10), List(13, 14))