List Groovy-从复杂嵌套映射聚合和建模数据
下面的代码片段中显示了groovy中的数据:List Groovy-从复杂嵌套映射聚合和建模数据,list,dictionary,groovy,List,Dictionary,Groovy,下面的代码片段中显示了groovy中的数据: def productAvailability = [ [id: 1, startDate: "2014-12-22", endDate: "2015-01-02", storeId: 1, productId: 1, categoryId: 1], [id: 4, startDate: "2014-12-24", endDate: "2015-01-08", storeId: 2, productId: 1, categoryId: 1],
def productAvailability = [
[id: 1, startDate: "2014-12-22", endDate: "2015-01-02", storeId: 1, productId: 1, categoryId: 1],
[id: 4, startDate: "2014-12-24", endDate: "2015-01-08", storeId: 2, productId: 1, categoryId: 1],
[id: 8, startDate: "2014-12-25", endDate: "2015-01-01", storeId: 2, productId: 3, categoryId: 1],
[id: 9, startDate: "2014-12-22", endDate: "2015-01-02", storeId: 1, productId: 3, categoryId: 1],
[id: 10, startDate: "2015-01-10", endDate: "2015-01-21", storeId: 1, productId: 1, categoryId: 1]
];
目标是获得如下结果:
产品统计
Product Id: 1 | Availability Index: 15 + 11 + 11 = 37.
Longest Available Products (Sort By Past Start Date *first* then, Store Id):
1. "2014-12-24" to "2015-01-08" in store id 2. (15 days)
2. "2014-12-22" to "2015-01-02" in store id 1. (11 days)
3. "2015-01-10" to "2015-01-21" in store id 1. (11 days)
Product Id: 3 | Availability Index: 7 + 11 = 18.
Longest Available Products (Sort By Past Start Date *first* then, Store Id):
1. "2014-12-22" to "2015-01-02" in store id 1. (11 days)
2. "2014-12-25" to "2015-01-01" in store id 2. (7 days)
Store Id: 1 | Availability Index: 11 + 11 + 11 = 33.
Most Available Product (sort by most available product, then sort by product id):
1. Product Id: 3 on ["2014-12-22" to "2015-01-02"] (11 days)
2. Product Id: 1 on ["2014-12-22" to "2015-01-02", "2015-01-10" to "2015-01-21"] (11 days)
Store Id: 2 | Availability Index: 15 + 7 = 22.
Most Available Product (sort by most available product, then sort by product id):
1. Product Id: 1 on ["2014-12-24" to "2015-01-08"] (15 days)
2. Product Id: 3 on ["2014-12-25" to "2015-01-01"] (7 days)
Total Availability Index: 37 + 18 or 33 + 22 = 55.
商店统计数据
Product Id: 1 | Availability Index: 15 + 11 + 11 = 37.
Longest Available Products (Sort By Past Start Date *first* then, Store Id):
1. "2014-12-24" to "2015-01-08" in store id 2. (15 days)
2. "2014-12-22" to "2015-01-02" in store id 1. (11 days)
3. "2015-01-10" to "2015-01-21" in store id 1. (11 days)
Product Id: 3 | Availability Index: 7 + 11 = 18.
Longest Available Products (Sort By Past Start Date *first* then, Store Id):
1. "2014-12-22" to "2015-01-02" in store id 1. (11 days)
2. "2014-12-25" to "2015-01-01" in store id 2. (7 days)
Store Id: 1 | Availability Index: 11 + 11 + 11 = 33.
Most Available Product (sort by most available product, then sort by product id):
1. Product Id: 3 on ["2014-12-22" to "2015-01-02"] (11 days)
2. Product Id: 1 on ["2014-12-22" to "2015-01-02", "2015-01-10" to "2015-01-21"] (11 days)
Store Id: 2 | Availability Index: 15 + 7 = 22.
Most Available Product (sort by most available product, then sort by product id):
1. Product Id: 1 on ["2014-12-24" to "2015-01-08"] (15 days)
2. Product Id: 3 on ["2014-12-25" to "2015-01-01"] (7 days)
Total Availability Index: 37 + 18 or 33 + 22 = 55.
上面打印的结果是产品统计和商店统计。
我会寻求优化,高效,易于理解的解决方案来打印上述结果
我试图从上述数据中获得结果:
// productAvailability => see the declaration variable above in the beginning of question!
List aggregateDates = productAvailability.collect({[
storeId: it.storeId,
productId: it.productId,
availabilityIndex: Date.parse("YYYY-MM-dd", it.endDate) - Date.parse("YYYY-MM-dd", it.startDate)
]});
println "Total Availability Index: " + aggregateDates.clone().sum({ it.availabilityIndex });
println "Total Products: " + aggregateDates.clone().unique({ it.productId }).count({ it.productId });
println "Total Stores: " + aggregateDates.clone().unique({ it.storeId }).count({ it.storeId });
println "Average Availability Index: " + aggregateDates.clone().sum({ it.availabilityIndex }) / aggregateDates.size();
正如您在上面的代码片段中所看到的,我可以很容易地获得聚合总和AVG,并计算productAvailability数据中有多少产品和存储。然而,我很难根据产品和门店使用日期范围获得可用性,以实现上述目标
请参阅下面使用日期范围的代码
def dailyDatesAvailability = [:] as Map<Date, Integer>;
def dailyStoresAvailability = [:].withDefault {0} as Map<Integer, Integer>;
def dailyProductsAvailability = [:].withDefault {0} as Map<Integer, Integer>;
(Date.parse("YYYY-MM-dd", "2014-12-01")).upto((Date.parse("YYYY-MM-dd", "2015-01-30"))) { Date runningDate ->
dailyDatesAvailability[runningDate] = 0;
productAvailability.each({ _availability ->
def _startDate = Date.parse("YYYY-MM-dd", _availability.startDate);
def _endDate = Date.parse("YYYY-MM-dd", _availability.endDate);
if (_startDate <= runningDate && _endDate >= runningDate) {
dailyDatesAvailability[runningDate]++;
dailyProductsAvailability[_availability.productId]++;
dailyStoresAvailability[_availability.storeId]++;
}
// Do something here to get the MOST available PRODUCT in a STORE with date ranges
});
/// or do something here....?
}
def dailydatesavaailability=[:]作为映射;
def dailyStoresAvailability=[:];
def dailyProductsAvailability=[:],默认为映射{0};
(日期解析(“YYYY-MM-dd”,“2014-12-01”))。截至(日期解析(“YYYY-MM-dd”,“2015-01-30”){日期运行日期->
dailyDatesAvailability[runningDate]=0;
productAvailability.each({u availability->
def _startDate=Date.parse(“YYYY-MM-dd”,“u availability.startDate”);
def _endDate=Date.parse(“YYYY-MM-dd”,_availability.endDate);
如果(_startDate=运行日期){
dailyDatesAvailability[运行日期]+;
dailyProductsAvailability[_availability.productId]++;
dailyStoresAvailability[_availability.storeId]++;
}
//在这里做点什么,在有日期范围的商店里买到最畅销的产品
});
///或者在这里做点什么。。。。?
}
使用Groovy打印上述目标的最佳方法是什么?请分享代码片段以进行测试。对此很感兴趣,并提出:
List<Range> simplify( List<Range> ranges ) {
ranges.drop( 1 ).inject( ranges.take( 1 ) ) { r, curr ->
// Find an overlapping range
def ov = r.find { curr.from <= it.to && curr.to >= it.from }
if( ov ) {
ov.from = [ curr.from, ov.from ].min()
ov.to = [ curr.to, ov.to ].max()
simplify( r )
}
else {
r << curr
}
}
}
def manipulate(data, primary, secondary) {
data.groupBy { it."$primary" }
.collect { id, vals ->
def joined = vals.collect { it ->
[ id: it.id,
range: Date.parse('yyyy-MM-dd', it.startDate)..Date.parse('yyyy-MM-dd', it.endDate),
key: secondary,
value: it."$secondary" ]
}.groupBy { it.value }
.collectMany { sid, ran -> simplify(ran.range).collect { [key: secondary, value: sid, range:it, days:(it.to - it.from)] } }
.sort { a, b -> b.days <=> a.days ?: a.value - b.value }
[name:primary, id:id, data:joined]
}
}
def dump(data) {
data.collect { a ->
def sum = a.data.days.sum()
println "$a.name: $a.id | availability index ${a.data.days.join(' + ')} = ${sum}"
a.data.eachWithIndex { row, idx ->
println " ${idx+1}. ${row.range.from.format('yyyy-MM-dd')} to ${row.range.to.format('yyyy-MM-dd')} in $row.key $row.value ($row.days days)"
}
sum
}
}
def productAvailability = [
[id: 1, startDate: "2014-12-22", endDate: "2015-01-02", storeId: 1, productId: 1, categoryId: 1],
[id: 4, startDate: "2014-12-24", endDate: "2015-01-08", storeId: 2, productId: 1, categoryId: 1],
[id: 8, startDate: "2014-12-25", endDate: "2015-01-01", storeId: 2, productId: 3, categoryId: 1],
[id: 9, startDate: "2014-12-22", endDate: "2015-01-02", storeId: 1, productId: 3, categoryId: 1],
[id: 10, startDate: "2015-01-10", endDate: "2015-01-21", storeId: 1, productId: 1, categoryId: 1]
];
def p = dump(manipulate(productAvailability, 'productId', 'storeId'))
println ''
def s = dump(manipulate(productAvailability, 'storeId', 'productId'))
println ''
println "Total Availability Index: ${p.join(' + ')} or ${s.join(' + ')} = ${[p.sum(), s.sum()].max()}"
请共享代码段以便能够测试。。感谢您使用“为我做编码工作”服务。目前所有高薪开发者都很忙。你能分享一下你迄今为止的一些尝试吗?@cfrick我更新了问题并添加了我尝试的代码片段。请参阅..@cfrick我更新了
aggregateDates
variable中日期操作的代码段在示例产品统计输出中id为10
的行发生了什么情况?@tim_yates很好!它应该包含在门店id 1中编号2“2014-12-22”到“2015-01-02”之后。此外,产品id 3还应该有额外的输出。请查看更新。我刚刚更新了产品统计输出,并修复了产品统计输出中的错误日期。请给我时间回顾一下,我昨天通过对开始日期和结束日期之间的差异进行排序,然后按商店和产品进行分组(与您的概念相同)解决了主要问题-我认为这比您的简单得多。我将稍后发布解决方案。但是你的解决方案给出了目标的作用。再次感谢蒂姆的努力,谢谢你!