Разделить карту с помощью Groovy - PullRequest
3 голосов
/ 06 января 2011

Я хочу разделить карту на массив карт. Например, если есть карта с 25 парами ключ / значение. Я хочу, чтобы массив карт содержал не более 10 элементов на каждой карте.

Как бы я это сделал в Groovy?

У меня есть решение, которое меня не волнует, есть ли лучшая версия:

  static def splitMap(m, count){
    if (!m) return

    def keys = m.keySet().toList()
    def result = []
    def num = Math.ceil(m?.size() / count)
    (1..num).each {
      def min = (it - 1) * count
      def max = it * count > keys.size() ? keys.size() - 1 : it * count - 1
      result[it - 1] = [:]
      keys[min..max].each {k ->
        result[it - 1][k] = m[k]
      }
    }
    result
  }

м это карта. Количество - это максимальное количество элементов на карте.

1 Ответ

6 голосов
/ 07 января 2011

Адаптируя мой ответ на этот вопрос при разделении списка , я придумал этот метод:

Map.metaClass.partition = { size ->
  def rslt = delegate.inject( [ [:] ] ) { ret, elem ->
    ( ret.last() << elem ).size() >= size ? ret << [:] : ret
  }
  rslt.last() ? rslt : rslt[ 0..-2 ]
}

Так что, если вы возьмете эту карту:

def origMap = [1:'a', 2:'b', 3:'c', 4:'d', 5:'e', 6:'f']

Все следующие утверждения проходят: -)

assert [ [1:'a'], [2:'b'], [3:'c'], [4:'d'], [5:'e'], [6:'f'] ] == origMap.partition( 1 )
assert [ [1:'a', 2:'b'], [3:'c', 4:'d'], [5:'e', 6:'f'] ]       == origMap.partition( 2 )
assert [ [1:'a', 2:'b', 3:'c'], [4:'d', 5:'e', 6:'f'] ]         == origMap.partition( 3 )
assert [ [1:'a', 2:'b', 3:'c', 4:'d'], [5:'e', 6:'f'] ]         == origMap.partition( 4 )
assert [ [1:'a', 2:'b', 3:'c', 4:'d', 5:'e'], [6:'f'] ]         == origMap.partition( 5 )
assert [ [1:'a', 2:'b', 3:'c', 4:'d', 5:'e', 6:'f'] ]           == origMap.partition( 6 )

Или как Category (чтобы избежать необходимости добавлять что-либо к metaClass из Map:

class MapPartition {
  static List partition( Map delegate, int size ) {
    def rslt = delegate.inject( [ [:] ] ) { ret, elem ->
      ( ret.last() << elem ).size() >= size ? ret << [:] : ret
    }
    rslt.last() ? rslt : rslt[ 0..-2 ]
  }
}

Тогда, где вам нужна эта функциональность, вы можете просто use Категория примерно так:

use( MapPartition ) {
  assert [ [1:'a'], [2:'b'], [3:'c'], [4:'d'], [5:'e'], [6:'f'] ] == origMap.partition( 1 )
  assert [ [1:'a', 2:'b'], [3:'c', 4:'d'], [5:'e', 6:'f'] ]       == origMap.partition( 2 )
  assert [ [1:'a', 2:'b', 3:'c'], [4:'d', 5:'e', 6:'f'] ]         == origMap.partition( 3 )
  assert [ [1:'a', 2:'b', 3:'c', 4:'d'], [5:'e', 6:'f'] ]         == origMap.partition( 4 )
  assert [ [1:'a', 2:'b', 3:'c', 4:'d', 5:'e'], [6:'f'] ]         == origMap.partition( 5 )
  assert [ [1:'a', 2:'b', 3:'c', 4:'d', 5:'e', 6:'f'] ]           == origMap.partition( 6 )
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...