如何用LINQ对已分组排序的外层数组内层按价格降序排序
Go LINQ 分组后内层数组排序(保持外层顺序)
需求说明
已通过LINQ完成商品按shopId分组,且外层分组已按组内最高商品价格降序排列完成。现需在不改变外层分组顺序的前提下,将每个分组内的商品数组按price字段降序排序。
结构体定义
// 商品结构体 type product struct { name string price int64 shopId int64 } // 分组结构体 type oneGroup struct { shopId int64 products []*product } // 最终输出的分组数组 var groupOut []oneGroup
原分组排序代码(已完成外层排序)
products := make([]*product, 0, 20) products = append(products, &product{name: "product66", price: 6666, shopId: 100}) products = append(products, &product{name: "product11", price: 1111, shopId: 100}) products = append(products, &product{name: "product44", price: 4444, shopId: 100}) products = append(products, &product{name: "product22", price: 2222, shopId: 200}) products = append(products, &product{name: "product77", price: 9999, shopId: 200}) products = append(products, &product{name: "product00", price: 0, shopId: 200}) products = append(products, &product{name: "product33", price: 3333, shopId: 300}) products = append(products, &product{name: "product88", price: 8888, shopId: 300}) products = append(products, &product{name: "product55", price: 5555, shopId: 300}) products = append(products, &product{name: "product99", price: 7777, shopId: 400}) var query []linq.Group // 按shopId分组,再按组内最高价格降序排列外层分组 linq.From(products).GroupByT( func(p *product) int64 { return p.shopId }, // 分组键:shopId func(p *product) *product { return p }, // 分组元素:商品对象 ).OrderByDescendingT( func(g linq.Group) int64 { // 获取组内商品的最高价格作为排序依据 return linq.From(g.Group).Select( func(x interface{}) interface{} { return x.(*product).price }, ).Max().(int64) }, ).ToSlice(&query)
解决方案
方式1:转换为oneGroup时处理内层排序
遍历已排序的外层分组,对每个分组内的商品数组单独降序排序,再封装为oneGroup类型:
// 初始化结果数组 groupOut = make([]oneGroup, 0, len(query)) for _, group := range query { // 提取当前分组的所有商品 prods := make([]*product, 0, len(group.Group)) for _, item := range group.Group { prods = append(prods, item.(*product)) } // 对商品按price降序排序 sort.Slice(prods, func(i, j int) bool { return prods[i].price > prods[j].price }) // 添加到结果数组 groupOut = append(groupOut, oneGroup{ shopId: group.Key.(int64), products: prods, }) }
方式2:LINQ链式调用中完成内层排序
直接在LINQ的链式调用中加入SelectT操作,完成分组到oneGroup的转换及内层排序,代码更连贯:
// 直接通过LINQ链式调用完成所有逻辑 linq.From(products).GroupByT( func(p *product) int64 { return p.shopId }, func(p *product) *product { return p }, ).OrderByDescendingT( func(g linq.Group) int64 { return linq.From(g.Group).Select( func(x interface{}) interface{} { return x.(*product).price }, ).Max().(int64) }, ).SelectT( func(g linq.Group) oneGroup { prods := make([]*product, 0, len(g.Group)) for _, item := range g.Group { prods = append(prods, item.(*product)) } // 内层商品降序排序 sort.Slice(prods, func(i, j int) bool { return prods[i].price > prods[j].price }) return oneGroup{ shopId: g.Key.(int64), products: prods, } }, ).ToSlice(&groupOut)
说明
两种方式均不会改变外层分组的原有顺序,仅对每个分组内部的商品数组进行排序。方式2将所有逻辑整合到LINQ链式调用中,代码更简洁。
内容的提问来源于stack exchange,提问作者王建森
相关产品推荐
相关产品推荐

