سؤال

أريد بعض الصنف لهذا:

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

لكنني لم أر أي شيء في المستندات ...هل فاتني شيء؟أم أنني مجرد كسول جدا؟

هل كانت مفيدة؟

المحلول

لقد واجهت مؤخرًا الحاجة إلى القيام بذلك بالضبط:تحويل القائمة إلى خريطة.تم نشر هذا السؤال قبل ظهور الإصدار 1.7.9 من Groovy، لذا فإن الطريقة collectEntries لم تكن موجودة بعد.إنه يعمل تمامًا مثل collectMap طريقة الذي تم اقتراحه:

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

إذا كنت عالقًا لسبب ما في إصدار Groovy الأقدم، فإن inject يمكن أيضًا استخدام الطريقة (كما هو مقترح هنا).هذه نسخة معدلة قليلاً وتأخذ تعبيرًا واحدًا فقط داخل الإغلاق (فقط من أجل حفظ الأحرف!):

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

ال + يمكن أيضًا استخدام المشغل بدلاً من <<.

نصائح أخرى

تحقق من "حقن".يطلق عليه خبراء البرمجة الوظيفية الحقيقية اسم "الطي".

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

وأثناء قيامك بذلك، ربما تريد تعريف الأساليب كفئات بدلاً من تعريفها مباشرة على metaClass.بهذه الطريقة، يمكنك تعريفه مرة واحدة لجميع المجموعات:

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

كان مجموعة من الطريقة غير متوفرة عند طرح هذا السؤال؟

أيضًا، إذا كنت تستخدم مجموعات Google (http://code.google.com/p/google-collections/)، يمكنك القيام بشيء مثل هذا:

  map = Maps.uniqueIndex(list, Functions.identity());

نعم...لقد لعبت مع هذا أكثر قليلاً وأعتقد أن هذه طريقة رائعة جدًا ...

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

إذا كان ما تحتاجه هو زوج بسيط من المفاتيح والقيمة، إذن الطريقة 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]]

لا أستطيع العثور على أي شيء مدمج في ...ولكن باستخدام ExpandoMetaClass يمكنني القيام بذلك:

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

يؤدي هذا إلى إضافة طريقة CollectMap إلى كافة قوائم ArrayLists...لست متأكدًا من سبب عدم نجاح إضافته إلى القائمة أو المجموعة..أعتقد أن هذا لسؤال آخر..ولكن الآن أستطيع أن أفعل هذا..

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

من القائمة إلى الخريطة المحسوبة بإغلاق واحد...بالضبط ما كنت أبحث عنه.

يحرر:السبب وراء عدم تمكني من إضافة الطريقة إلى قائمة الواجهات والمجموعة هو أنني لم أفعل هذا:

List.metaClass.enableGlobally()

بعد استدعاء الطريقة، يمكنك إضافة طرق إلى الواجهات..وهو ما يعني في هذه الحالة أن طريقة CollectMap الخاصة بي ستعمل على نطاقات مثل هذا:

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

الذي ينتج الخريطة:[0:0، 1:2، 2:4]

ماذا عن شيء مثل هذا؟

// 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']
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top