【发布时间】:2012-03-04 22:13:16
【问题描述】:
我在这里使用这一行来根据对象的名称对列表进行排序。
g.V.sort{it.name}
如果存在,我如何根据“名称”对其进行排序,如果不存在,我想按“标题”对其进行排序。如果两者都存在,我想先按“名称”排序,然后按“标题”排序。
我不是 Groovy 编码器,所以提前感谢您的帮助。
【问题讨论】:
我在这里使用这一行来根据对象的名称对列表进行排序。
g.V.sort{it.name}
如果存在,我如何根据“名称”对其进行排序,如果不存在,我想按“标题”对其进行排序。如果两者都存在,我想先按“名称”排序,然后按“标题”排序。
我不是 Groovy 编码器,所以提前感谢您的帮助。
【问题讨论】:
我不确定我是否正确理解了您的问题。也许你正在寻找这样的东西:
def things = [
[name: 'aaa', title: '222'],
[name: 'aaa', title: '333'],
[title: '222'],
[title: '111'],
[name: 'bbb', title: '111'],
[title: '333'],
[name: 'aaa', title: '111'],
]
things.sort { a, b ->
// Compare by name and then by title.
a.name <=> b.name ?: a.title <=> b.title
}
assert things == [
[title: '111'],
[title: '222'],
[title: '333'],
[name: 'aaa', title: '111'],
[name: 'aaa', title: '222'],
[name: 'aaa', title: '333'],
[name: 'bbb', title: '111'],
]
在这个看似无辜的比较函数内部发生的事情实际上是相当多的 Groovy 语法魔法。但这并不难。
首先,sort 方法被一个用作比较器的二进制函数调用(即,接受两个参数,a 和 b,如果 a b 返回 1,如果 a = = b)。
这个匿名函数:{ a, b -> a.name <=> b.name ?: a.title <=> b.title } 使用“spaceship operator”(<=>...这是一个宇宙飞船人!)首先按名称比较 a 和 b。
如果名称相等(或两者都为空),则 a.name <=> b.name 的结果为 0,它在 "Elvis operator" 中的计算错误(?:... 将其想象为笑脸),那么返回a.title <=> b.title 的结果。
否则,如果名称比较的结果不为 0,则在 Elvis 运算符中正确计算并返回该值。
这一切都考虑到您可以将空值与字符串进行比较,并且'any string' > null 始终成立(这与说'any string' <=> null == 1 相同)。
所以最终的结果是没有名字的元素先按标题排序,然后有名字和标题的元素先按名字再按标题排序。
我希望那是您正在寻找的。如果您期望排序元素的不同顺序,请随时在 cmets 中澄清它:)
在这种情况下,还可以使用一个记录不充分的 OrderBy 对象:
things.sort new OrderBy([{it.name}, {it.title}])
【讨论】:
name 属性,此解决方案将引发异常,但问题是“根据“名称”对其进行排序如果存在”
您可以使用Comparator 对集合进行排序。
g.V.sort { a, b ->
a.name <=> b.name ?: a.title <=> b.title
}
【讨论】:
这是我完全未经测试的努力,可能充满了错误
def comparator = {o1, o2 ->
// wording of question suggests title will always exist, if not, add more hasProperty checks
def diff = o1.title <=> o2.title
if (o1.hasProperty('name') && o2.hasProperty('name')) {
def nameDiff = o1.name <=> o2.name
if (nameDiff != 0) {
diff = nameDiff
}
}
diff
} as Comparator
def someList = []
// populate the list...
someList.sort(comparator)
【讨论】: