遍历/修改Groovy数据结构

时间:2015-04-23 02:10:29

标签: groovy closures traversal

我正在开发一个项目,该项目将以专有格式读取某些数据,将其收集到一些统一的Groovy数据结构中,并以整齐的XML(或JSON,尚未决定)格式写出来。 我是Groovy的新手,但是,这个项目是Ant构建项目,Groovy似乎是最好的方法。

到目前为止,我能够读取数据,创建原子结构,使用>>连接它们。运算符,并使用MarkupBuilder将它们无缝地转储到XML(比我在Java中使用它更容易)。但是,当我需要稍微修改收集的结构,或者遍历它们以组成一些聚合数据时,我现在陷入困境。

为了说明,假设我们收集了数据,因此它等同于:

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
}

我们正努力实现以下目标,例如:

  1. 删除所有“bug”项目(假设,我们正在撰写一份列表,以便在我们经销商的网站上发布)。或者,所有“功能”(如果是我们的售前维修小组)。
  2. 浏览列表并确保所有“年”属性均为4位
  3. 废弃所有“awd”属性,将其移至“功能”列表
  4. 所以我们最终得到这样的结构:

    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
    }
    

    实际上,我可以通过原始结构组成一个新列表(我的数据不是那么大,需要就地编辑),但是我如何首先遍历这个结构呢? / p>

    哦,还有一个术语问题。也许,我只是在谷歌上搜索一个错误的关键字...这个实体在代码中定义:它也被称为“闭包”,或者它有一个不同的术语吗?

1 个答案:

答案 0 :(得分:1)

inventory,它实际上可以用

之类的东西来表示
@Immutable(copyWith = true)
class Car {
    String make
    String model
    int year
    String color
    boolean awd

    List<String> features
    List<String> bugs
}

由于你可以编写一个新列表(并且一般说来没有理由不这样做),你可以添加@Immutable注释。作为一种副作用&#34;您可以添加copyWith = true来获取复制方法。

inventory的定义可能如下所示:

    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"])
        ]

它为您提供了不可变的数据表示。 然后,您可以使用集合API遍历和更改数据。在你的情况下:

    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
            } 

每个转换都是单独应用的(并且只有不可变的实例流经该管道)。

如果您确实要删除空错误列表和/或awd属性,请定义目标类:

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

并向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) }