গ্রোভির একটি তালিকা থেকে একটি মানচিত্র তৈরির জন্য শর্টকাট?


106

আমি এর জন্য কিছুটা সরন্ডহ্যান্ড চাই:

Map rowToMap(row) {
    def rowMap = [:];
    row.columns.each{ rowMap[it.name] = it.val }
    return rowMap;
}

জিডিকে স্টাফগুলি যেভাবে দেওয়া হয়েছে তা দিয়ে, আমি এমন কিছু করতে সক্ষম হবেন আশা করি:

Map rowToMap(row) {
    row.columns.collectMap{ [it.name,it.val] }
}

তবে আমি ডক্সে কিছু দেখিনি ... আমি কি কিছু মিস করছি? নাকি আমি খুব অলসভাবেই আছি?


2
আমিরের মন্তব্য এখন সঠিক উত্তর: stackoverflow.com/a/4484958/27561
রবার্ট ফিশার

উত্তর:


119

আমি সম্প্রতি হুবহু এটি করার প্রয়োজনটি পেরিয়েছি: একটি তালিকা মানচিত্রে রূপান্তরিত। গ্রোভির সংস্করণ 1.7.9 প্রকাশের আগে এই প্রশ্নটি পোস্ট করা হয়েছিল, সুতরাং পদ্ধতিটি collectEntriesএখনও বিদ্যমান ছিল না। এটি প্রস্তাবিতcollectMap পদ্ধতি হিসাবে ঠিক কাজ করে :

Map rowToMap(row) {
    row.columns.collectEntries{[it.name, it.val]}
}

যদি কোনও কারণে আপনি কোনও পুরানো গ্রোভির সংস্করণে আটকে থাকেন তবে injectপদ্ধতিটিও ব্যবহার করা যেতে পারে ( এখানে প্রস্তাবিত হিসাবে )। এটি একটি সামান্য পরিবর্তিত সংস্করণ যা বন্ধের অভ্যন্তরে কেবলমাত্র একটি অভিব্যক্তি গ্রহণ করে (কেবল চরিত্র সংরক্ষণের জন্য!):

Map rowToMap(row) {
    row.columns.inject([:]) {map, col -> map << [(col.name): col.val]}
}

+অপারেটর এছাড়াও পরিবর্তে ব্যবহার করা যেতে পারে <<


28

"ইনজেকশন" পরীক্ষা করে দেখুন। রিয়েল ফাংশনাল প্রোগ্রামিং উইংস এটিকে "ভাঁজ" বলে call

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

এবং আপনি যখন এটির দিকে রয়েছেন, আপনি সম্ভবত মেটা ক্লাসে ডান পরিবর্তে বিভাগগুলি হিসাবে পদ্ধতিগুলি সংজ্ঞায়িত করতে চান। এইভাবে, আপনি সমস্ত সংগ্রহের জন্য এটি একবার সংজ্ঞায়িত করতে পারেন:

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')
}

আমি অনুমান করি এর গ্রোভিতে ইঞ্জেকশনটির নামকরণ করা হয়েছে কারণ এটি ইনজেকশন দ্বারা অনুপ্রাণিত হয়েছিল: ইন: ইন স্মলটাল্ক: | তালিকা যোগফল list: = অর্ডারডকলেশন নতুন যুক্ত: 1; যোগ করুন: 2; যোগ করুন: 3; নিজেকে। যোগফল: = তালিকা ইনজেকশন: 0 ইন: [: এ: বি | ক + খ]। প্রতিলিপি cr; দেখান: যোগফল। "প্রিন্ট 6"
অলিপি

13

ছিল groupBy পদ্ধতি পাওয়া যায় না এই প্রশ্ন জিজ্ঞাসা করা হয়েছিল?


না-এর মতো মনে হচ্ছে - এটি ১.৮.১১, ২০১১ সাল থেকে।
এমভিএমএন

আপনি যেমন গ্রুপবাইয়ের জন্য ডকুমেন্টেশনে দেখতে পাচ্ছেন, এটি মূলত উপাদানগুলিকে গ্রুপগুলিতে বিভক্ত করে, যেখানে প্রতিটি গ্রুপে একটি নির্দিষ্ট কীটির সাথে মেলে এমন উপাদান রয়েছে। অতএব, এটির রিটার্নের ধরনটি Map<K, List<V>>মনে হয় যে ওপি রিটার্নের ধরণ সহ কোনও পদ্ধতি Map<K, V>খুঁজছে, সুতরাং গ্রুপবি এই ক্ষেত্রে কাজ করে না।
ক্রিজিসিক প্রজিগডজকি

6

আপনার যা প্রয়োজন তা যদি একটি সাধারণ কী-মান জোড় হয় তবে পদ্ধতিটি collectEntriesযথেষ্ট। উদাহরণ স্বরূপ

def names = ['Foo', 'Bar']
def firstAlphabetVsName = names.collectEntries {[it.charAt(0), it]} // [F:Foo, B:Bar]

তবে আপনি যদি কোনও মাল্টিম্যাপের অনুরূপ একটি কাঠামো চান, যেখানে প্রতি কী অনুসারে একাধিক মান রয়েছে, তবে আপনি groupByপদ্ধতিটি ব্যবহার করতে চান

def names = ['Foo', 'Bar', 'Fooey']
def firstAlphabetVsNames = names.groupBy { it.charAt(0) } // [F:[Foo, Fooey], B:[Bar]]


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

এখন মানচিত্র বা সংগ্রহের যে কোনও সাবক্লাসে এই পদ্ধতিটি রয়েছে ...

এখানে আমি এটি কোনও মানচিত্রে কী / মানটি বিপরীত করতে ব্যবহার করি

[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

1

আমি অন্তর্নির্মিত কিছুই খুঁজে পাচ্ছি না ... তবে এক্সপ্যানডোমেটা ক্লাস ব্যবহার করে আমি এটি করতে পারি:

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

এটি সমস্ত অ্যারেলিস্টগুলিতে কালেক্টম্যাপ পদ্ধতি যুক্ত করে ... আমি নিশ্চিত না কেন এটি তালিকা বা সংগ্রহের সাথে যুক্ত করা কার্যকর হয়নি .. আমার ধারণা এটি অন্য প্রশ্নের জন্য ... তবে এখন আমি এটি করতে পারি ...

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

এক বন্ধ হয়ে তালিকা থেকে গণনা করা মানচিত্রের ... ঠিক আমি যা খুঁজছিলাম।

সম্পাদনা করুন: আমি ইন্টারফেসের তালিকা এবং সংগ্রহের জন্য পদ্ধতিটি যুক্ত করতে না পারার কারণ হ'ল আমি এটি করি নি:

List.metaClass.enableGlobally()

এই পদ্ধতির কল করার পরে, আপনি ইন্টারফেসগুলিতে পদ্ধতিগুলি যুক্ত করতে পারেন .. যার অর্থ এই যে আমার কালেক্টম্যাপ পদ্ধতিটি এই জাতীয় রেঞ্জগুলিতে কাজ করবে:

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

যা মানচিত্র দেয়: [0: 0, 1: 2, 2: 4]


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

এটি মূলত আমার প্রশ্নের মতোই ... আমার কাছে কেবলমাত্র [it.k] = it.v .put এর পরিবর্তে মানচিত্র ছিল আমি একটি লাইনার খুঁজছিলাম।
ড্যানব
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.