116

私はこれのためにいくつかのソートハンドが欲しいです:

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] }
}

しかし、私はドキュメントに何も見ていません...私は何かが欠けていますか?それとも私はあまりにも怠惰ですか?

4

8 に答える 8

30

「注入」をご覧ください。真の関数型プログラミングの専門家はそれを「フォールド」と呼んでいます。

columns.inject([:]) { memo, entry ->
    memo[entry.name] = entry.val
    return memo
}

そして、あなたがそれに取り組んでいる間、おそらくメソッドを metaClass で定義するのではなく、Categories として定義したいと思うでしょう。そうすれば、すべてのコレクションに対して 1 回定義できます。

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')
}
于 2008-10-13T18:48:46.723 に答える
13

この質問がされたとき、groupByメソッドは利用できませんでしたか?

于 2010-12-19T20:34:54.860 に答える
6

また、Googleコレクション(http://code.google.com/p/google-collections/)を使用している場合は、次のようにすることができます。

  map = Maps.uniqueIndex(list, Functions.identity());
于 2008-08-20T22:32:57.030 に答える
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 のサブクラスには、このメソッドがあります...

ここでは、マップのキー/値を逆にするために使用します

[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
于 2008-08-20T23:28:29.767 に答える
1

組み込まれているものが見つかりません...しかし、ExpandoMetaClassを使用してこれを行うことができます:

ArrayList.metaClass.collectMap = {Closure callback->
    def map = [:]
    delegate.each {
        def r = callback.call(it)
        map[r[0]] = r[1]
    }
    return map
}

これにより、すべてのArrayListsにcollectMapメソッドが追加されます...リストまたはコレクションへの追加が機能しなかった理由がわかりません..別の質問のためだと思います...しかし、今はこれを行うことができます...

assert ["foo":"oof", "42":"24", "bar":"rab"] ==
            ["foo", "42", "bar"].collectMap { return [it, it.reverse()] }

リストから計算されたマップまで、1つのクロージャーで...まさに私が探していたものです。

編集:メソッドをインターフェイスのリストとコレクションに追加できなかった理由は、これを行わなかったためです。

List.metaClass.enableGlobally()

そのメソッド呼び出しの後で、インターフェイスにメソッドを追加できます。この場合、私のcollectMapメソッドは次のような範囲で機能します。

(0..2).collectMap{[it, it*2]}

これにより、マップが生成されます:[0:0、1:2、2:4]

于 2008-08-20T22:25:12.197 に答える
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']
于 2008-09-29T17:41:19.937 に答える