Groovy 如何基于两个键对贴图值求和?
我有一张地图,上面有两个键(Groovy 如何基于两个键对贴图值求和?,groovy,Groovy,我有一张地图,上面有两个键(customer和price),如下所示: [ customer: ['Clinton', 'Clinton', 'Mark', 'Antony', 'Clinton', 'Mark'], price: [15000.0, 27000.0, 28000.0, 56000.0, 21000.0, 61000.0] ] customer和price值通过其索引位置映射,即customer列表中的名字与第一个价格映射,依此类推 范例 Cliton pri
customer
和price
),如下所示:
[
customer: ['Clinton', 'Clinton', 'Mark', 'Antony', 'Clinton', 'Mark'],
price: [15000.0, 27000.0, 28000.0, 56000.0, 21000.0, 61000.0]
]
customer
和price
值通过其索引位置映射,即customer
列表中的名字与第一个价格映射,依此类推
范例
Cliton price is 15000.0
Cliton price 27000.0
Mark price 28000.0
Antony price 56000.0
Clinton price 21000.0
Mark price 61000.0
我想把价格按名称分类汇总一下。预期产出:
Clinton price 63000
Mark price 89000
Antony price 56000
Groovy中是否有任何内置函数来实现这一点,或者我是否需要通过编写自己的函数来迭代映射和求和值?下面的内容创建了一个由
客户聚合的价格的映射:
def vals = (0..(-1+map.customer.size()))
.collect{['name':map.customer[it], 'price': map.price[it]]}
.groupBy{it['name']}
.collectEntries{[(it.key): it.value.collect{it['price']}.sum()]}
这导致:
[Clinton:63000.0, Mark:89000.0, Antony:56000.0]
它本质上是一个迭代,使用从0
到map.customer.size()-1
的一系列数字,然后是一组带值和的by。在这样的问题中,我们应该始终计划将每个条目作为列表中的单独对象,以使其在列表中直观且易于操作
在这种情况下,同样的结果也可以自然得到
def list = [
[customer: 'Clinton', price: 15000.0],
[customer: 'Clinton', price: 27000.0],
[customer: 'Mark', price: 28000.0],
[customer: 'Antony', price: 56000.0],
[customer: 'Clinton', price: 21000.0],
[customer: 'Mark', price: 61000.0]
]
def map = list.groupBy({it.customer}).collectEntries {k, v -> [k, v.price.sum()]}
map.each {println it}
您可以从两个列表上的转置开始,以获得customer和price的元组。从这里开始,它基本上与其他答案类似(按客户分组,与客户一起构建地图并汇总价格)。例如:
这个版本是从@cfrick的答案中派生出来的,除了求和之外还有一个选择。使用带有默认值的映射并不是“功能性的”/“声明性的”,但可以说,以后更容易查找代码(即维护):
鉴于:
def map = [
customer: ['Clinton', 'Clinton', 'Mark', 'Antony', 'Clinton', 'Mark'],
price: [15000.0, 27000.0, 28000.0, 56000.0, 21000.0, 61000.0]
]
方法:
def getSumMap = { data ->
def result = [:].withDefault { c -> 0.0 }
[data.customer, data.price].transpose().each { c, p -> result[c] += p }
result
}
assert 63000.0 == getSumMap(map)['Clinton']
assert 89000.0 == getSumMap(map)['Mark']
assert 56000.0 == getSumMap(map)['Antony']
我猜OP的问题是因为他收到了一张给定格式的地图。如果您提供将输入格式转换为您提供的格式的方法,您的答案会更好。好的。这是一个要点。在这种情况下,它与@cfrick的解决方案相同谢谢。我得到的数值低于这个数值[Clinton:15000.0,Clinton:27000.0,Mark:28000.0,Antony:56000.0,Clinton:21000.0,Mark:61000.0]谢谢。我发现以下错误:groovy.lang.MissingMethodException:没有方法签名:java.math.BigDecimal.plus()适用于参数类型:(groovy.util.slurpersupport.NodeChild)值:[15000.0]可能的解决方案:plus()、plus(java.math.MathContext)、plus(java.lang.Character)、plus(java.lang.Number)、plus(java.lang.String)、ulp()groovy.lang.MissingMethodException:没有方法签名:java.math.BigDecimal.plus()适用于参数类型:(groovy.util.slurpersupport.NodeChild)值:[15000.0]答案适用于groovy 2.4.9。我已经把它贴在这里了-。。。您使用的是什么版本的Groovy和Java?
def getSumMap = { data ->
def result = [:].withDefault { c -> 0.0 }
[data.customer, data.price].transpose().each { c, p -> result[c] += p }
result
}
assert 63000.0 == getSumMap(map)['Clinton']
assert 89000.0 == getSumMap(map)['Mark']
assert 56000.0 == getSumMap(map)['Antony']