Группировка каталогов более функциональным способом

1

Может ли кто-нибудь дать мне представление о том, как преобразовать этот код 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))
  • 0
    Используйте grouped на вашей map .
  • 0
    Я попробовал, но это не будет точным, потому что некоторые размеры могут быть слишком маленькими. map.groupBy (map.sum / limit)
Теги:
functional-programming

2 ответа

1
Лучший ответ

Вот одно из возможных решений:

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
  • 0
    прохладно! оно работает. здорово. как работает :: чем он отличается от: + append и +: prepend.
  • 1
    Это эквивалентно +: но работает только со List .
Показать ещё 4 комментария
2

Я не уверен, что это самый приятный подход. Но я бы сделал что-то вроде:

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)
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню