我想对此进行一些分类:
Map rowToMap(row) {
def rowMap = [:];
row.columns.each{ rowMap[it.name] = it.val }
return rowMap;
}
考虑到GDK的方式,我希望能够做到这样的事情:
Map rowToMap(row) {
row.columns.collectMap{ [it.name,it.val] }
}
但我在文档中没有看到任何内容......我错过了什么吗?还是我太懒了?
答案 0 :(得分:109)
我最近遇到了这样做的需要:将列表转换为地图。这个问题是在Groovy 1.7.9版本发布之前发布的,所以方法collectEntries
还不存在。它与collectMap
方法that was proposed完全相同:
Map rowToMap(row) {
row.columns.collectEntries{[it.name, it.val]}
}
如果由于某种原因您遇到了较旧的Groovy版本,也可以使用inject
方法(如建议here)。这是一个稍微修改过的版本,在闭包内只占用一个表达式(只是为了保存字符!):
Map rowToMap(row) {
row.columns.inject([:]) {map, col -> map << [(col.name): col.val]}
}
也可以使用+
运算符代替<<
。
答案 1 :(得分:28)
查看“注入”。真正的函数编程让人称之为“折叠”。
columns.inject([:]) { memo, entry ->
memo[entry.name] = entry.val
return memo
}
而且,当你在它的时候,你可能想要在metaClass上将方法定义为Categories而不是right。这样,您可以为所有集合定义一次:
class PropertyMapCategory {
static Map mapProperty(Collection c, String keyParam, String valParam) {
return c.inject([:]) { memo, entry ->
memo[entry[keyParam]] = entry[valParam]
return memo
}
}
}
使用示例:
use(PropertyMapCategory) {
println columns.mapProperty('name', 'val')
}
答案 2 :(得分:13)
当问到这个问题时,groupBy方法不可用吗?
答案 3 :(得分:5)
此外,如果你使用谷歌收藏(http://code.google.com/p/google-collections/),你可以这样做:
map = Maps.uniqueIndex(list, Functions.identity());
答案 4 :(得分:5)
def collectMap = {Closure callback->
def map = [:]
delegate.each {
def r = callback.call(it)
map[r[0]] = r[1]
}
return map
}
ExpandoMetaClass.enableGlobally()
Collection.metaClass.collectMap = collectMap
Map.metaClass.collectMap = collectMap
现在Map或Collection的任何子类都有这个方法......
这里我用它来反转Map中的键/值
[1:2, 3:4].collectMap{[it.value, it.key]} == [2:1, 4:3]
在这里我用它来创建列表中的地图
[1,2].collectMap{[it,it]} == [1:1, 2:2]
现在我只是把它弹出到一个类中,当我的应用程序启动时调用它,这个方法在我的代码中都可用。
编辑:
将方法添加到所有数组......
Object[].metaClass.collectMap = collectMap
答案 5 :(得分:5)
如果您需要的是一个简单的键值对,那么方法nginx-rtmp-module
就足够了。例如
collectEntries
但是如果你想要一个类似于Multimap的结构,其中每个键有多个值,那么你想要使用def names = ['Foo', 'Bar']
def firstAlphabetVsName = names.collectEntries {[it.charAt(0), it]} // [F:Foo, B:Bar]
方法
groupBy
答案 6 :(得分:1)
我找不到任何内置的东西......但是使用ExpandoMetaClass我可以这样做:
ArrayList.metaClass.collectMap = {Closure callback->
def map = [:]
delegate.each {
def r = callback.call(it)
map[r[0]] = r[1]
}
return map
}
这会将collectMap方法添加到所有ArrayLists ...我不确定为什么将它添加到List或Collection不起作用..我猜这是另一个问题...但现在我可以这样做...
assert ["foo":"oof", "42":"24", "bar":"rab"] ==
["foo", "42", "bar"].collectMap { return [it, it.reverse()] }
从List到计算出的Map有一个闭包......正是我在寻找的东西。
编辑:我无法将方法添加到接口List和Collection的原因是因为我没有这样做:
List.metaClass.enableGlobally()
在该方法调用之后,您可以向接口添加方法..在这种情况下,这意味着我的collectMap方法将在以下范围内工作:
(0..2).collectMap{[it, it*2]}
产生地图:[0:0,1:2,2:4]
答案 7 :(得分:0)
这样的事情怎么样?
// setup
class Pair {
String k;
String v;
public Pair(def k, def v) { this.k = k ; this.v = v; }
}
def list = [ new Pair('a', 'b'), new Pair('c', 'd') ]
// the idea
def map = [:]
list.each{ it -> map.putAt(it.k, it.v) }
// verify
println map['c']