【问题标题】:Grouping and sorting nested collections in Groovy在 Groovy 中对嵌套集合进行分组和排序
【发布时间】:2016-07-28 04:34:30
【问题描述】:

我有以下 POGO:

class Widget {
    String name
    Integer order
    // lots of other fields

    Widget(Integer order) {
        super()
        this.order = order
    }
}

我有一个List<Widget> 并试图将它们放入一个List<Set<Widget>> 中,它们按order 字段分组。因此,如果我有 3 个具有以下相应顺序的小部件:{ 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

所以这里的想法是“未排序/未分组”List&lt;Widget&gt; 可能非常大,并且许多小部件可能包含相同的顺序。我们希望以相同的顺序对所有小部件进行分组( order = 1, order = 2, etc.) 到相同的内部Set,然后将这些集合按升序添加到外部List。因此,如果我们要在上面的示例中添加第 4 个小部件:

Widget w4 = new Widget(2)

这个小部件属于另一个二阶小部件:

Set<Widget> secondOrderWidgets = []
secondOrderWidgets << w3 // order = 2
secondOrderWidgets << w4 // order = 2

所以我正在尝试编写一个以List&lt;Widget&gt; 作为输入的方法,将它们按order 分组,然后按升序对这些组/集进行排序。 order 字段保证为非空,但可以是任何有效的正 (1+) 整数。我最好的尝试是导致各种运行时/动态异常:

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
}

谁能看出我哪里出错了?

【问题讨论】:

    标签: sorting groovy collections


    【解决方案1】:

    我无法重现您的错误。由于equalshashCodeWidget 类中的实现方式,可能会发生这种情况。我设法使用@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]
    ] 
    

    【讨论】:

    • 轰——完成了!谢谢@Will P(+1 和绿色检查)。只是 FWIW,我特别需要一个 List&lt;Set&lt;Widget&gt;&gt; 而你上面的 sortMethod 似乎给了我一个 List&lt;List&lt;Widget&gt;&gt;。所以我只需要调整它来遍历groupBy返回的Map&lt;Integer,Widget&gt;的键/值对,并通过toSet()显式地将每个值设置为一个集合。但是你帮我完成了困难的部分(排序+分组)-谢谢!!!
    • @smeeb 很高兴它有帮助!
    猜你喜欢
    • 1970-01-01
    • 2021-02-24
    • 2013-07-25
    • 1970-01-01
    • 2016-06-28
    • 1970-01-01
    • 1970-01-01
    • 2015-09-18
    相关资源
    最近更新 更多