如何按现有属性对列表进行排序

10
我正在使用这行代码根据对象名称对列表进行排序。
g.V.sort{it.name}

如果存在"name",我该如何基于它进行排序?如果不存在,我想按"title"排序。如果两者都存在,我想先按"name"排序,然后再按"title"排序。

我不是Groovy编码人员,所以提前感谢您的帮助。

3个回答

17

我不确定我正确理解了你的问题。也许像这样的东西是你在寻找的:

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则返回1,如果a == b则返回0)。

这个匿名函数:{ 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运算符中评估为真,并返回该值。
所有这些都考虑到您可以将null值与字符串进行比较,并且'any string' > null始终成立(这与说'any string' <=> null == 1相同)。
因此,最终结果是没有名称的元素首先按标题排序,然后按名称和标题排序的元素首先按名称排序,然后按标题排序。
希望这正是您所寻找的内容。如果您期望排序后的元素顺序有所不同,请在评论中澄清 :)
更新

在这种情况下,还有一个不太被记录的OrderBy对象可以使用:

things.sort new OrderBy([{it.name}, {it.title}])

1
如果对象没有“name”属性,此解决方案将抛出异常,但问题说“如果存在”,则基于“name”对其进行排序。 - Dónal
@Don 可能吧。问题没有明确说明“不存在”是指该属性为 null(或空字符串)还是根本没有该属性。所以我选择了最简单的路线 =D - epidemian
2
我想你可以把“if it exists”解释为“不为空”,这对你来说非常方便 :) - Dónal

5
你可以使用 Comparator 对集合进行排序。
g.V.sort { a, b ->
    a.name <=> b.name ?: a.title <=> b.title
}

0

这是我完全未经测试的努力,可能充满了错误。

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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接