Может ли кто-нибудь дать мне представление о том, как преобразовать этот код Scala (императивный способ Java) в более функциональный способ?
Это группировка каталогов, скажем, всего 4 ГБ, разделяющих каталоги/файлы на 4 группы с лимитом 1 ГБ для каждой группы, добавляя каждую группу в список.
object MyMapper {
def main(args: Array[String]) {
var map: Map[String, Long] = Map[String, Long]();
map += ("a" -> 5);
map += ("b" -> 5);
map += ("c" -> 3);
map += ("d" -> 2);
map += ("e" -> 4);
map += ("f" -> 2);
map += ("g" -> 1);
limitMapper(map)
}
def limitMapper(map: Map[String, Long]): Unit = {
var offset = 0L;
var result = Vector[Vector[String]]()
var list = Vector[String]()
val iterator: Iterator[(String, Long)] = map.toVector.iterator
val LIMIT: Int = 10
while (iterator.hasNext) {
val (path, size) = iterator.next()
println((path, size))
offset += size
if (offset > LIMIT) {
offset = size;
result = result :+ list
list = Vector[String]()
}
list = list :+ path
}
//add remaining paths
if (list.size > 0) {
result = result :+ list
list = Vector[String]()
}
println(result)
println(s"LIMIT = $LIMIT")
}
}
Output:
(e,4)
(f,2)
(a,5)
(b,5)
(g,1)
(c,3)
(d,2)
Vector(Vector(e, f), Vector(a, b), Vector(g, c, d))
Вот одно из возможных решений:
val (_, lastList, otherLists) = map.foldLeft(0L, List[String](), List[List[String]]()) {
case ((soFar, newList, oldLists), (path, size)) =>
if (soFar + size > limit)
(size, List(path), newList :: oldLists)
else
(soFar + size, path :: newList, oldLists)
}
lastList :: otherLists
+:
но работает только со List
.
Я не уверен, что это самый приятный подход. Но я бы сделал что-то вроде:
val map = ...
val limit = 1073741824L
val res = map.foldLeft(Vector(Vector[String]())){ case (result, (path, size)) =>
if(result.last.map(map(_)).sum + size > limit) {
result :+ Vector(path)
} else result.updated(result.size - 1, result.last :+ path)
}
grouped
на вашейmap
.