简体   繁体   English

Groovy 列表:按元素列表分组

[英]Groovy List: Group by by a list of elements

I basically want to group maps, I must group by car and color and sums its prices, if any of the groups prices are greater than 25, group the result by car, color and motor and multiply the sum * 3, first part it's completed, but I'm stuck at the second group by:我基本上想对地图进行分组,我必须按汽车和颜色分组并对其价格求和,如果任何一组价格大于 25,则按汽车、颜色和电机对结果进行分组并乘以总和 * 3,第一部分完成,但我被困在第二组:

def row1 = ["car":'A',"color":'B',"motor":'C', "price": 12]
def row2 = ["car":'A',"color":'B',"motor":'C', "price": 12]
def row3 = ["car":'A',"color":'B',"motor":'D', "price": 2]
def row4 = ["car":'B',"color":'B',"motor":'D', "price": 13]
def arrayRows = []
arrayRows.add(row1)
arrayRows.add(row2)
arrayRows.add(row3)
arrayRows.add(row4)
println(arrayRows) //[[car:A, color:B, motor:C, price:12], [car:A, color:B, motor:C, price:12], [car:A, color:B, motor:D, price:2], [car:B, color:B, motor:D, price:13]]
def groups = arrayRows.groupBy {row -> [Car:row.car, Color:row.color] }.collect{k , v ->
    [
        car:k.Car,
        color:k.Color,
        motor:v.motor,
        price:v.collect { it.price }.sum()
    ]
}
println(groups) //[[car:A, color:B, motor:[C, C, D], price:26], [car:B, color:B, motor:[D], price:13]]
for(group in groups){
    if (group.price > 25){ //26>25
        println group //[car:A, color:B, motor:[C, C, D], price:26]
        //def groupByCarColorMotor = arrayRows.groupBy {[Car: group.car, Color: group.color, Motor:?]} | Must group by car, color and motor, and multiply * 3 it's price but since motor is an array, I'm not sure how to do so, I've tried groupBy { row -> group.it.motor} etc
    }
}

How am I supposed to group by the second time if I have: [car:A, color:B, motor:[C, C, D] And I should group by by: [car:A, color:B, motor:C] And [car:A, color:B, motor:D]如果我有:[car:A, color:B, motor:[C, C, D] 我应该如何分组:[car:A, color:B, motor: C] 和 [car:A, color:B, motor:D]

Expected output should be: [ ["car":'A',"color":'B',"motor":'C', "price": 72, ["car":'A',"color":'B',"motor":'D', "price": 6] ]预期输出应为:[ ["car":'A',"color":'B',"motor":'C', "price": 72, ["car":'A',"color": 'B',“电机”:'D',“价格”:6]]

Edit;编辑; I almost managed to do it, the problem is that I'm getting an array of arrays of maps, and also you will probably get the idea behind it too.我几乎设法做到了,问题是我得到了一组地图数组,而且你可能也会明白它背后的想法。

def arrayRows = [ 
        ["car":'A',"color":'B',"motor":'C', "price": 12],
        ["car":'A',"color":'B',"motor":'C', "price": 12],
        ["car":'A',"color":'B',"motor":'D', "price": 2],
        ["car":'B',"color":'B',"motor":'D', "price": 13]
        ]

println(arrayRows) //[[car:A, color:B, motor:C, price:12], [car:A, color:B, motor:C, price:12], [car:A, color:B, motor:D, price:2], [car:B, color:B, motor:D, price:13]]
def groups = arrayRows.groupBy {row -> [Car:row.car, Color:row.color] }.collect{k , v ->
    [
            car:k.Car,
            color:k.Color,
            price:v.collect { it.price }.sum()
    ]
}.findAll{it.price > 25}

def groupByCarColor = []
for (group in groups){
    groupByCarColor.add(arrayRows.findAll{ row -> row.car == group.car && row.color == group.color}.groupBy {row -> [Car:group.car, Color:group.color, Motor:row.motor] }.collect{k , v ->
        [
                car:k.Car,
                color:k.Color,
                motor:k.Motor,
                price:v.collect { it.price }.sum()*3
        ]
    })
}

Output: [[[car:A, color:B, motor:C, price:72], [car:A, color:B, motor:D, price:6]]]输出:[[[car:A, color:B, motor:C, price:72], [car:A, color:B, motor:D, price:6]]]

Something straight-forward for your home assignment:家庭作业的一些直截了当的东西:

def arrayRows = [
["car":'A',"color":'B',"motor":'C', "price": 13],
["car":'A',"color":'B',"motor":'D', "price": 14],
["car":'B',"color":'B',"motor":'D', "price": 13],
]

List out = arrayRows.groupBy{ [ car:it.car, color:it.color ] }.inject( [] ){ List res, k, v ->
  if( 25 < v*.price.sum() ) v.each{ res << ( it + [ price:it.price * 3 ] ) }
  res
}

assert out.toString() == '[[car:A, color:B, motor:C, price:39], [car:A, color:B, motor:D, price:42]]'

Your goal here is to find the groups via a triplet - but you want to filter out those groups where a predicate fails on a subgroup.您的目标是通过三元组找到组 - 但您想要过滤掉谓词在子组上失败的那些组。 Eg例如

def arrayRows = [ 
    [car:'A', motor:'C', color:'B',price: 12],
    [car:'A', motor:'C', color:'B',price: 12],
    [car:'A', motor:'D', color:'B',price:  2],
    [car:'B', motor:'D', color:'B',price: 13],
]


def output = arrayRows.inject([:].withDefault{ 0 }){ acc, row -> // group by the triplet and sum up the price
    acc[row.subMap(['car','motor','color'])]+=row.price; acc
}.groupBy{ k, _ -> // group by the filter criteria tuple
    k.subMap(['car','color'])
}.findAll{ _, v -> // eliminate the tuple-groups where price is to low
    v.values().sum() > 25
}.collectMany{ _, vs -> // reshape the data
    vs.collect{ k, v ->
        k + [price: v * 3]
    }
}

assert output==[[car:"A", motor:"C", color:"B", price:72], [car:"A", motor:"D", color:"B", price:6]]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM