2016-10-08 1 views
1

Я хочу группировать по 3 свойствам, но не каждое свойство является собственным вложенным массивом. То, что я хочу:Groovy способ группировки более чем одним свойством только на один уровень глубиной

def values=[ 
    [day:1,month:1,year:1], 
    [day:1,month:1,year:1], 
    [day:2,month:1,year:1], 
    [day:2,month:2,year:1] 
]; 

/*...some code to group by DAY, MONTH, AND YEAR 

..desired result is that items with the same day, 
    month, and year end up in a one level deep subarray 
*/ 

    [ 
    [[day:1,month:1,year:1],[day:1,month:1,year:1]], 
    [[day:2,month:1,year:1]] , 
    [[day:2,month:2,year:1]] 
    ]; 

Использования GroupBy() метода с несколькими затворами дает мне каждое сгруппированное имущество в качестве своего собственного вложенного массива, как [год [месяц [день []]]], который не Что мне нужно.

ответ

1

Рассмотрим следующий использование inject создать карту, ключи которого соответствующая группа, и значения являются искомыми списки:

(Редактировать: обновлено строительство ключа карты, на комментарий)

def values=[ 
    [day:1,month:1,year:1], 
    [day:1,month:1,year:1], 
    [day:2,month:1,year:1], 
    [day:2,month:2,year:1] 
]; 

def groupMap = [:].withDefault{ key -> [] } 

def result = values.inject(groupMap) { val, m -> 
    val["${m.'day'}:${m.'month'}:${m.'year'}"] << m 
    val 
}.values() 

assert [[day:1, month:1, year:1], [day:1, month:1, year:1]] == result[0] 
assert [[day:2, month:1, year:1]] == result[1] 
assert [[day:2, month:2, year:1]] == result[2] 
+0

awesome; Благодарю. – user2782001

+0

вызов .groupBy ({...}), за которым следует .values ​​(), также приведет к такому же результату. – norganos

+0

также не забудьте дважды проверить шаблон «ключ», используемый для группировки. в этом примере используется простая строка (достаточно справедливая, чтобы показать концепцию), но 11 января и 1 ноября были бы неразличимы (если входные значения действительно похожи на простые состояния простых вопросов) – norganos

2

Вы хотите принять свою функцию groupBy, чтобы просто делать то, что вам нужно. В этом примере на ваших картах уже есть личность, с которой вы хотите сгруппировать их. Так что это достаточно для результата, которого вы ищете:

def values=[ 
    [day:1,month:1,year:1], 
    [day:1,month:1,year:1], 
    [day:2,month:1,year:1], 
    [day:2,month:2,year:1], 
] 

// just the identity 
println values.groupBy().values() 
// => [[[day:1, month:1, year:1], [day:1, month:1, year:1]], [[day:2, month:1, year:1]], [[day:2, month:2, year:1]]] 

И если вы на самом деле имеете больше значения в ваших картах есть, вы можете использовать subMap для группы на один уровень:

// submap only the needed keys (in case there is more in `values` than just your identity 
println values.groupBy{ it.subMap(["year","month","day"]) }.values() 
// => [[[day:1, month:1, year:1], [day:1, month:1, year:1]], [[day:2, month:1, year:1]], [[day:2, month:2, year:1]]] 

На стороне nitpicking: это вложенные карты, которые вы получаете.

Смежные вопросы