Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Group list of numbers into groups based on the range from the lowest number

Tags:

scala

Assuming there the list of numbers and a range value, I want to group them into groups, in which the item in each group is within the range from the lowest number, and sort them.

For example, I have a list val l = List(1,2,3,4,5,6,7,8,9,10) and the range val range = 2. Then, I'm looking for a way to output the following result: result = List(List(1,2,3), List(4,5,6), List(7,8,9), List(10)). Which means if range = 0 then only identical numbers are in the same group.

At the moment, I use the following method

val minVal = l.min
val range1 = (minVal + range).toDouble
val groups = l.foldLeft(Map[Int, List[Int]]())((result, num) => {
    val numRange = math.ceil(num / range1).toInt
    if (result.contains(numRange)) {
        result.updated(numRange, num :: result(numRange))
    } else {
        result.updated(numRange, List(num))
    }
})
groups.keys.toList.sortBy(k => k).map(groups(_))

It works in most cases except when range = 0 and slowestNum != 1. E.g. for the list val l = List(2,3,4,5,6,7,8,9,10) and the range val range = 2, the result is List(List(2), List(4, 3), List(6, 5), List(8, 7), List(10, 9)).

So, I wonder if there is any other way to solve this problem.

like image 863
Long Thai Avatar asked Dec 25 '22 23:12

Long Thai


1 Answers

Why complicate?

def coll(l: List[Int], range: Int): List[List[Int]] =
    if (l.isEmpty) Nil else {
        val (b, a) = l.span((l.head - range to l.head + range).contains)
        b :: coll(a, range)
    }

So, this algorithm collects numbers into a group until the number are in the plus/minus range.

val list = List(7,4,1,9,10,20,50,52,30)
coll(list, 3)
res6: List[List[Int]] = List(List(7, 4), List(1), List(9, 10), List(20), List(50, 52), List(30))

If you want each group by itself sorted, then call res6.map(_.sorted).

like image 76
Rok Kralj Avatar answered May 18 '23 01:05

Rok Kralj