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

时间:2012-03-04 22:13:16

标签: java sorting groovy

我在这里使用这一行来根据对象的名称对列表进行排序。

g.V.sort{it.name}

如果存在,我如何根据“名称”对其进行排序,如果不存在,我想按“标题”对其进行排序。如果两者都存在,我想首先按“名称”排序,然后按“标题”排序。

我不是Groovy程序员,所以感谢您的帮助。

3 个答案:

答案 0 :(得分:13)

我不确定我是否理解你的问题。也许这就是你要找的东西:

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,如果&lt; b,则返回-1,如果&gt; b则返回1 0如果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}相同。

所以最后的结果是没有名字的元素首先按标题排序,然后名称和标题的元素首先按名称排序,然后按标题排序。

我希望那就是你要找的东西。如果您期望排序元素的不同排序,请随时在评论中澄清它:)

更新

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

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

答案 1 :(得分:5)

您可以使用Comparator对收藏品进行排序。

g.V.sort { a, b ->
    a.name <=> b.name ?: a.title <=> b.title
}

答案 2 :(得分: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)