我有三张地图,一张清单给我一张去年卖车的地图,第二张图给出了六个月卖车的清单 第三张地图给了我上个月卖车的清单。见下文
totalYear = [
[brand:"BMW"],
[brand:"BMW"],
[brand:"BMW"],
[brand:"BMW"],
[brand:"BMW"],
[brand:"BMW"],
[brand:"BMW"],
[brand:"mercedes"],
[brand:"mercedes"],
[brand:"mercedes"]
]
totalSixMonth = [
[brand:"BMW"],
[brand:"BMW"],
[brand:"BMW"],
[brand:"mercedes"],
[brand:"mercedes"]
]
totalMonth = [
[brand:"BMW"],
[brand:"mercedes"]
]
如何将这些地图组合成一个地图,如
total = [
[totalMonth:"1", totalSixMonth:"3", totalYear:"7", brand:"BMW"],
[totalMonth:"1", totalSixMonth:"2", totalYear:"3", brand:"mercedes"]
]
我尝试groupBy
和collect
,但他们没有给出正确的结果。谁能帮忙解决这个问题?
答案 0 :(得分:4)
你可以这样做:
// Something to extract counts
def counts = { input -> input.groupBy { it.brand }.collectEntries { k, v -> [k, v.size()] } }
def result = [totalYear:totalYear, totalSixMonth:totalSixMonth, totalMonth:totalMonth]
.collectMany { name, list -> // (A)
counts(list).collect { brand, num -> [(name):num, brand:brand] }
}
.groupBy { it.brand } // (B)
.collect { it.value } // (C)
.collect {
it.inject { a, b -> a + b } // (D)
}
给出结果:
[
['totalYear':7, 'brand':'BMW', 'totalSixMonth':3, 'totalMonth':1],
['totalYear':3, 'brand':'mercedes', 'totalSixMonth':2, 'totalMonth':1]
]
稍微解释一下,这里的每个阶段的数据是什么样的:
在(A)的collectMany之后,我们有以下形式的数据:
[['totalYear':7, 'brand':'BMW'], ['totalYear':3, 'brand':'mercedes'], ['totalSixMonth':3, 'brand':'BMW'], ['totalSixMonth':2, 'brand':'mercedes'], ['totalMonth':1, 'brand':'BMW'], ['totalMonth':1, 'brand':'mercedes']]
在({B)groupBy
之后,这变为:
['BMW':[['totalYear':7, 'brand':'BMW'], ['totalSixMonth':3, 'brand':'BMW'], ['totalMonth':1, 'brand':'BMW']], 'mercedes':[['totalYear':3, 'brand':'mercedes'], ['totalSixMonth':2, 'brand':'mercedes'], ['totalMonth':1, 'brand':'mercedes']]]
然后,我们可以在(C)处丢弃此地图的键,以获取地图列表的列表:
[[['totalYear':7, 'brand':'BMW'], ['totalSixMonth':3, 'brand':'BMW'], ['totalMonth':1, 'brand':'BMW']], [['totalYear':3, 'brand':'mercedes'], ['totalSixMonth':2, 'brand':'mercedes'], ['totalMonth':1, 'brand':'mercedes']]]
对于这些地图列表中的每一个,我们都可以使用inject
将它们折叠到(D)的单个地图中,因此我们最终得到的是地图列表和最终结果。
对于相同的结果可能有一个较短的方法,因为这感觉就像它有太多的groupBy调用......
另一种选择,但不会短得多(如果有的话)
def result = [totalYear:totalYear, totalSixMonth:totalSixMonth, totalMonth:totalMonth]
.collectMany { name, list ->
list.countBy { it.brand }.collect { brand, count ->
[(name): count, brand: brand]
}
}
.groupBy { it.brand }.values()*.inject { a, b -> a + b }
答案 1 :(得分:1)
您可以做的第一件事就是将三个Map
合并为一个,每个变量都是关键,Map
是值。之后,您将需要一系列转换。
def total = [totalYear: totalYear, totalSixMonth: totalSixMonth, totalMonth: totalMonth].collectEntries { label, maps ->
[(label): maps.countBy { it.brand} ]
}.inject([:]) { result, label, counts ->
counts.entrySet().each { entry ->
if(!result[entry.key]) result[entry.key] = [:]
result[entry.key][(label)] = entry.value
}
result
}.collect { brand, counts -> [brand: brand] << counts }
collectEntries()
累积总数:
[totalYear:[BMW:7, mercedes:3], totalSixMonth:[BMW:3, mercedes:2], totalMonth:[BMW:1, mercedes:1]]
inject()
按品牌分组总数:
[BMW:[totalYear:7, totalSixMonth:3, totalMonth:1], mercedes:[totalYear:3, totalSixMonth:2, totalMonth:1]]
最后,collect()
构建了最终列表:
[['brand':'BMW', 'totalYear':7, 'totalSixMonth':3, 'totalMonth':1], ['brand':'mercedes', 'totalYear':3, 'totalSixMonth':2, 'totalMonth':1]]
注意:您要求Map
,但演示了List
或Map
。我参加了演示。