在Grails中对列表或getAll进行排序

时间:2012-06-26 02:17:20

标签: grails groovy

我想在我的域类中实现默认排序顺序,并立即发现它不适用于getAll方法。没什么大不了的,我只是使用了list。问题是域类中的默认排序顺序不允许您指定多个排序字段(as seen here)。

我的目标是首先按照Foo对象的名称,然后按照自己的名称对所有Bar个对象进行排序。

class Foo {
    String name
    String Bar
}

class Bar {
    String name
}

如何在域类中实现这一点,所以每次调用.list()时都不必指定长/讨厌的比较器?

我的一次尝试:

static Comparator getComparator() { 
    def c = { a, b -> 
    def result = a.bar.name.compareTo( b.bar.name ); 
        if ( result == 0 ) {
            result = a.name.compareTo( b.name );
        }
    }
    return c as Comparator
}

然后我可以打电话给Foo.list(Foo.getComparator()) ...如果我能让它发挥作用。

更新

我认为我在这里非常接近,只是在同一种类型的闭包中实现两次比较时遇到了麻烦。

Foo.list().sort{ a, b ->
    def result = a.bar.name <=> b.bar.name;
    // Things mess up when I put this if statement in.
    if( result == 0 ) {
        a.name <=> b.name
    }
}

迪斯科!

class Foo { // My domain class
    // ...

    static Comparator getComparator() {
        def c =[
            compare: { a, b ->
                def result = a.bar.name <=> b.bar.name;
                if( result == 0 ) {
                    result = a.name <=> b.name
                }
                return result
            }
        ] as Comparator
    }

    // ...
}

在我的控制器中实现如下:

Foo.list().sort( Foo.getComparator() )

PS:

上述工作,但Jeff Storey在我的回答之后在他的回答中发布了一些代码,并且他的代码工作并且比我的好得多,所以使用它:)

2 个答案:

答案 0 :(得分:4)

在您的情况下,让Foo实施Comparable是否有意义并且实施可以按照您的描述进行比较?然后,当您对列表中的对象进行排序时,因为它们是Comparable,它们将正确排序。

如果你实现Comparable没有意义,你需要指定一个比较器进行排序。

以下是基于您的评论的示例代码:

编辑:

class Person implements Comparable<Person> {

   String firstName
   String lastName

   int compareTo(Person other) {
       int lastNameCompare = lastName <=> other.lastName
       return lastNameCompare != 0 ? lastNameCompare : firstName <=> other.firstName
   }

   String toString() {
     "${lastName},${firstName}"
   }
}

def people = [new Person(firstName:"John",lastName:"Smith"), new Person(firstName:"Bill",lastName:"Jones"), new Person(firstName:"Adam",lastName:"Smith")]
println "unsorted = ${people}"
println "sorted = ${people.sort()}" 

打印:

unsorted = [Smith,John, Jones,Bill, Smith,Adam]
sorted = [Jones,Bill, Smith,Adam, Smith,John]

答案 1 :(得分:2)

为了进一步简化上面的帖子(我会评论它但我还没有代表),你可以使用elvis运算符链接groovy比较运算符:

class Person implements Comparable<Person> {

    String firstName
    String lastName

    int compareTo(Person other) {
        return lastName <=> other.lastName ?: firstName <=> other.firstName
    }

    String toString() {
        "${lastName},${firstName}"
    }
}

def people = [new Person(firstName:"John",lastName:"Smith"), new Person(firstName:"Bill",lastName:"Jones"), new     Person(firstName:"Adam",lastName:"Smith")]
println "unsorted = ${people}"
println "sorted = ${people.sort()}"

这会给你相同的结果,因为在groovy的眼中0被认为是假的,这将使它看到链中的下一个条件。