如何使用groupby在Groovy中为地图值选择对象字段

时间:2012-06-24 11:27:52

标签: groovy

我有一个带有getName()和getYearOfBirth()方法的Person对象的人员列表。我正在使用groupBy对Person对象进行分组。我正在使用groupBy对Person对象进行分组,但我只希望将名称放入地图中,因为Person将来会有很多其他字段。这些年是关键。

    class Person {
        String name
        int yearOfBirth
    }       

    def people = [ 
        new Person(name:"Tom", yearOfBirth:1985),
        new Person(name:"Abigail", yearOfBirth:1987),
        new Person(name:"Joyce", yearOfBirth:1984),
        new Person(name:"James", yearOfBirth:1987),
        new Person(name:"Scott", yearOfBirth:1985),
        new Person(name:"Ruth", yearOfBirth:1984)
    ]           

    //people.groupBy(_.year) mapValues (_ map (_.name))  how to map here?

这是Scala app

的直接端口

2 个答案:

答案 0 :(得分:2)

一种解决方案是:

def nameInYear = people.groupBy { it.yearOfBirth }
                       .collectEntries { [ (it.key):it.value.name ] }
assert nameInYear[ 1984 ] == [ 'Joyce', 'Ruth' ]

因此,按照他们的出生年份对他们进行分组,以获得YEAR-> ListOfPeople地图 然后,对于这些分组中的每一个,收集YEAR-> ListOfNames

的地图

答案 1 :(得分:0)

另一个更为迫切的解决方案是:

def namesByYear = [:].withDefault { [] } 
people.each { namesByYear[it.yearOfBirth] << it.name }

assert namesByYear[1985] == ['Tom', 'Scott']

使用inject可以将同样的事物转换为一个表达式,但我认为它变得不那么可读了:

def namesByYear = people.inject([:].withDefault { [] }) { map, p ->
    map[p.yearOfBirth] << p.name
    map
}