简体   繁体   English

使用Groovy收集闭包将列表处理为分组的子列表

[英]Using Groovy collect closure to process list into grouped sublists

Given my Widget class: 鉴于我的Widget类:

class Widget {
    String name
    WidgetType type
    boolean isRad
}

enum WidgetType {
    Fizz, Buzz, Foo
}

My groovy code will be handed a List<Widget> that may be populated like so: 我的常规代码将交给List<Widget> ,它可能是这样填充的:

List<Widget> allWidgets = []
Widget w1 = new Widget(name: "W1", type: WidgetType.Fizz, isRad: true)
Widget w2 = new Widget(name: "W2", type: WidgetType.Fizz, isRad: true)
Widget w3 = new Widget(name: "W3", type: WidgetType.Buzz, isRad: false)
Widget w4 = new Widget(name: "W4", type: WidgetType.Buzz, isRad: false)
Widget w5 = new Widget(name: "W5", type: WidgetType.Foo, isRad: true)
Widget w6 = new Widget(name: "W6", type: WidgetType.Foo, isRad: false)

allWidgets << w1
allWidgets << w2
allWidgets << w3
allWidgets << w4
allWidgets << w5
allWidgets << w6

What I want to accomplish is the grouping of all elements in allWidgets according to their Widget#type . 我要完成的是根据allWidgetsWidget#type对所有元素进行分组。 So effectively, turning the above list into multiple lists (1 per type ) like so: 如此有效地将上面的列表变成多个列表(每种type 1个),如下所示:

List<Widget> fizzWidgets = []
List<Widget> buzzWidgets = []
List<Widget> gooWidgets = []
Widget w1 = new Widget(name: "W1", type: WidgetType.Fizz, isRad: true)
Widget w2 = new Widget(name: "W2", type: WidgetType.Fizz, isRad: true)
Widget w3 = new Widget(name: "W3", type: WidgetType.Buzz, isRad: false)
Widget w4 = new Widget(name: "W4", type: WidgetType.Buzz, isRad: false)
Widget w5 = new Widget(name: "W5", type: WidgetType.Foo, isRad: true)
Widget w6 = new Widget(name: "W6", type: WidgetType.Foo, isRad: false)

fizzWidgets << w1
fizzWidgets << w2

buzzWidgets << w3
buzzWidgets << w4

fooWidgets << w5
fooWidgets << w6

I believe that the collect closure can be used here, but all my attempts thus far have failed, my best being: 相信可以在此处使用collect闭包,但是到目前为止,我的所有尝试都以失败告终,我最好的尝试是:

allWidgets.collect { widget ->
    it.type
}

Any ideas what I can do here? 有什么想法我可以在这里做什么? And while I would accept a pure Java answer, I'm really hoping for something really elegant and...well, groovy. 虽然我会接受一个纯Java的答案,但我真的希望有一种非常优雅,...好时髦的东西。

What you need is not collect but groupBy : 您需要的不是collect而是groupBy

allWidgets.groupBy { it.type }

As a result a Map<WidgetType, List<Widget>> will be returned. 结果Map<WidgetType, List<Widget>>将返回Map<WidgetType, List<Widget>>

Demo: 演示:

enum WidgetType {
    Fizz, Buzz, Foo
}

class Widget {
    String name
    WidgetType type
    boolean isRad
}

List<Widget> allWidgets = [
    Widget w1 = new Widget(name: "W1", type: WidgetType.Fizz, isRad: true),
    Widget w2 = new Widget(name: "W2", type: WidgetType.Fizz, isRad: true),
    Widget w3 = new Widget(name: "W3", type: WidgetType.Buzz, isRad: false),
    Widget w4 = new Widget(name: "W4", type: WidgetType.Buzz, isRad: false),
    Widget w5 = new Widget(name: "W5", type: WidgetType.Foo, isRad: true),
    Widget w6 = new Widget(name: "W6", type: WidgetType.Foo, isRad: false),
]

def grouped = allWidgets.groupBy { it.type }
List<Widget> fizzWidgets = grouped[WidgetType.Fizz]
List<Widget> buzzWidgets = grouped[WidgetType.Buzz]
List<Widget> fooWidgets = grouped[WidgetType.Foo]

assert fizzWidgets.size() == 2
assert fizzWidgets.every { it.type == WidgetType.Fizz }
assert buzzWidgets.size() == 2
assert buzzWidgets.every{ it.type == WidgetType.Buzz }
assert fooWidgets.size() == 2
assert fooWidgets.every { it.type == WidgetType.Foo }


assert grouped instanceof Map
assert grouped.keySet().every { it instanceof WidgetType }
assert grouped.values().every { it instanceof List }
assert grouped.values().flatten().every { it instanceof Widget }

Here you can find groupBy docs. 在这里您可以找到groupBy文档。

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

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