Melintasi/memodifikasi struktur data Groovy

Saya sedang mengembangkan proyek yang akan membaca data tertentu dalam format kepemilikan, mengumpulkannya ke dalam struktur data Groovy terpadu, dan menuliskannya dalam format XML yang rapi (atau, JSON, belum diputuskan). Saya benar-benar pemula di Groovy, tetapi, proyeknya adalah proyek pembuatan Ant, Groovy tampaknya merupakan cara terbaik untuk melakukannya.

Sejauh ini baik-baik saja, saya dapat membaca data, membuat struktur atom, menggabungkannya menggunakan operator >>, dan membuangnya dengan mulus ke XML dengan MarkupBuilder (jauh lebih mudah daripada jika saya melakukannya di Java). Namun, sekarang saya terjebak pada titik ketika saya perlu sedikit memodifikasi struktur yang dikumpulkan, atau melintasinya untuk menyusun beberapa data agregat.

Sebagai ilustrasi, misalkan kita mengumpulkan data sehingga setara dengan:

def inventory = {
    car (make: "Subaru", model: "Impreza WRX", year: 2010, color: "Blue") {
        feature ("Premium sound")
        feature ("Brembo brakes")
        bug ("Leaks oil")
        bug ("Needs new transmission")
    }
    car (make: "Jeep", model: "Wrangler", year: 13, awd: true) {
        feature ("Soft top")
        bug ("Doesn't start")
        bug ("Flooded")
    }
    // blahblahblah
}

dan kami mencoba mencapai hal berikut, misalnya:

  1. Hapus semua item "bug" (misalkan, kami sedang membuat daftar untuk dipublikasikan di situs web dealer kami). Atau, semua "fitur" (jika itu untuk regu perbaikan pra-penjualan kami).
  2. Periksa daftarnya dan pastikan semua atribut "tahun" terdiri dari 4 digit
  3. Hapus semua atribut "awd", pindahkan ke daftar "fitur".

jadi kita berakhir dengan struktur seperti ini:

def inventory = {
    car (make: "Subaru", model: "Impreza WRX", year: 2010, color: "Blue") {
        feature ("Premium sound")
        feature ("Brembo brakes")
    }
    car (make: "Jeep", model: "Wrangler", year: 2013) {
        feature ("AWD")
        feature ("Soft top")
    }
    // blahblahblah
}

Sebenarnya, saya baik-baik saja dengan menelusuri struktur asli dan membuat daftar baru (data saya tidak terlalu besar sehingga memerlukan pengeditan di tempat), tetapi bagaimana cara saya menelusuri struktur ini?

Oh, dan pertanyaan tentang terminologi. Mungkin, saya baru saja mencari kata kunci yang salah di Google... Entitas ini seperti yang didefinisikan dalam kode: apakah disebut "penutupan" juga, atau ada istilah lain untuk itu?


person Andy Kovtun    schedule 23.04.2015    source sumber
comment
karena kode tidak ada data yang asyik, Anda harus melakukan transformasi sebelum atau sesudah DSL Anda di sana. sampai sekarang tidak begitu jelas, bagaimana sebenarnya semua ini dirangkai dan pada representasi perantara kode asyik Anda di atas. apakah seseorang menulisnya dan Anda menjalankannya di pembuat markup?   -  person cfrick    schedule 23.04.2015


Jawaban (1)


Melihat inventory, sebenarnya bisa diwakili oleh sesuatu seperti

@Immutable(copyWith = true)
class Car {
    String make
    String model
    int year
    String color
    boolean awd

    List<String> features
    List<String> bugs
}

Karena Anda tidak keberatan membuat daftar baru (dan secara umum ada beberapa alasan untuk tidak melakukannya), Anda dapat menambahkan anotasi @Immutable. Sebagai "efek samping" Anda dapat menambahkan copyWith = true untuk mendapatkan metode penyalinan.

Definisi inventory bisa terlihat seperti ini:

    def inventory = [
        new Car(
            make: "Subaru",
            model: "Impreza WRX",
            year: 2010,
            color: "Blue",
            features: ["Premium sound", "Brembo brakes"],
            bugs: ["Leaks oil", "Needs new transmission"]),
        new Car(
            make: "Jeep",
            model: "Wrangler",
            year: 13,
            awd: true,
            features: ["Soft top"],
            bugs: ["Doesn't start", "Flooded"])
        ]

yang memberi Anda representasi data Anda yang tidak dapat diubah. Kemudian Anda dapat melintasi dan mengubah data Anda menggunakan API pengumpulan. Dalam kasus Anda:

    def result = inventory
        .collect { it.copyWith(bugs: []) }
        .collect { it.copyWith(year: 
                     it.year < 2000 ? it.year + 2000 : it.year) }
        .collect {
            if (it.awd) { 
                it.copyWith(features: it.features + "AWD")
            } else {
                it
            } 

Setiap transformasi diterapkan secara individual (dan hanya ada instance abadi yang mengalir melalui pipeline tersebut).


Jika Anda benar-benar ingin menghapus daftar bug kosong dan/atau properti awd, tentukan kelas target:

class FixedCar {
    String make
    String model
    int year
    String color

    List<String> features

    static FixedCar apply(Car car) {
        new FixedCar(
            make: car.make,
            model: car.model,
            year: car.year,
            color: car.color,
            features: car.features)
    }
}

dan tambahkan panggilan lain ke collect:

    def result = inventory
        .collect { it.copyWith(bugs: []) }
        .collect { it.copyWith(year: 
                     it.year < 2000 ? it.year + 2000 : it.year) }
        .collect {
            if (it.awd) { 
                it.copyWith(features: it.features + "AWD")
            } else {
                it
            } 
        }.collect { FixedCar.apply(it) }
person Beryllium    schedule 27.04.2015