[英]Grouping and sorting nested collections in Groovy
I have the following POGO: 我有以下POGO:
class Widget {
String name
Integer order
// lots of other fields
Widget(Integer order) {
super()
this.order = order
}
}
I have a List<Widget>
and am trying to put them into a List<Set<Widget>>
where they are grouped by the order
field. 我有一个List<Widget>
并尝试将它们放入List<Set<Widget>>
,在其中将它们按order
字段分组。 So if I have 3 widgets with the following respective orders: { 3, 1, 2 }
then I would have an outer List
of size 3 and each element in that list would be a Set
of size 1. I could manually produce this in code via: 因此,如果我有3个分别按以下顺序List
的小部件: { 3, 1, 2 }
那么我将有一个大小为3的外部List
,并且该列表中的每个元素都是一个大小为1的Set
。我可以在代码中手动生成通过:
Widget w1 = new Widget(3)
Widget w2 = new Widget(1)
Widget w3 = new Widget(2)
// Now sort them by order manually:
Set<Widget> firstOrderWidgets = []
firstOrderWidgets << w2 // order = 1
Set<Widget> secondOrderWidgets = []
secondOrderWidgets << w3 // order = 2
Set<Widget> thirdOrderWidgets = []
thirdOrderWidgets << w1 // order = 3
List<Set<Widget>> sortedCorrectly = []
sortedCorrectly << firstOrderWidgets // All widgets w/ order = 1
sortedCorrectly << secondOrderWidgets // All widgets w/ order = 2
sortedCorrectly << thirdOrderWidgets // All widgets w/ order = 3
So the idea here is that the "unsorted/ungrouped" List<Widget>
could be quite large, and many widgets could contain the same order. 因此,这里的想法是“未排序/未分组”的List<Widget>
可能会很大,并且许多小部件可能包含相同的顺序。 We want to group all widgets with the same order (order = 1, order = 2, etc.) into the same inner Set
and then add those sets to the outer List
in ascending order. 我们希望将具有相同顺序(order = 1,order = 2等)的所有小部件分组到相同的内部Set
,然后将这些集合按升序添加到外部List
中。 So if we were to add a 4th widget to the example above: 因此,如果我们要在上面的示例中添加第四个小部件:
Widget w4 = new Widget(2)
This widget belongs with the other 2nd order widget: 此小部件与另一个二阶小部件一起属于:
Set<Widget> secondOrderWidgets = []
secondOrderWidgets << w3 // order = 2
secondOrderWidgets << w4 // order = 2
So I'm trying to write a method that take List<Widget>
as input, groups them by order
and then sorts those groups/sets in ascending order. 因此,我试图编写一种方法,将List<Widget>
作为输入,按order
它们进行分组,然后按升序对这些组/集进行排序。 The order
field is guaranteed to be non-null, but could be any valid positive (1+) integer. 保证order
字段为非空值,但可以是任何有效的正(1+)整数。 My best attempt is causing all sorts of runtime/dynamic exceptions: 我的最佳尝试是导致各种运行时/动态异常:
List<Set<Widget>> sortWidgets(List<Widget> toSort) {
def groupedByOrder = toSort.groupBy({ widget -> widget.order })
groupedByOrder = groupedByOrder.sort()
List<Set<Widget>> sortedList = []
groupedByOrder.each { order, widgets ->
sortedList << new HashSet(widgets)
}
sortedList
}
Can anyone spot where I'm going awry? 谁能发现我要去哪里?
I couldn't manage to reproduce your error. 我无法重现您的错误。 It can happen due to how equals
and hashCode
are implemented in your Widget
class. 由于在Widget
类中如何实现equals
和hashCode
因此可能会发生这种情况。 I managed to get a working example using @Canonical
: 我设法得到一个使用@Canonical
的工作示例:
@groovy.transform.Canonical
class Widget {
int order
String toString() { "Widget(order=$order, ${hashCode()})" }
}
widget = { new Widget(order: it) }
w1 = widget(3)
w2 = widget(1)
w3 = widget(2)
w4 = widget(2)
w5 = widget(2)
allWidgets = [w4, w1, w2, w5, w3]
def sortWidgets(widgets) {
widgets.sort(false) { it.order }.groupBy { it.order }.values() as List
}
assert sortWidgets(allWidgets) == [
[w2],
[w3, w4, w5],
[w1]
]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.