【问题标题】:How to sort a list by existing properties如何按现有属性对列表进行排序
【发布时间】:2012-03-04 22:13:16
【问题描述】:

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

g.V.sort{it.name}

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

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

【问题讨论】:

    标签: java sorting groovy


    【解决方案1】:

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

    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 -&gt; a.name &lt;=&gt; b.name ?: a.title &lt;=&gt; b.title } 使用“spaceship operator”(&lt;=&gt;...这是一个宇宙飞船人!)首先按名称比较 a 和 b。

    如果名称相等(或两者都为空),则 a.name &lt;=&gt; b.name 的结果为 0,它在 "Elvis operator" 中的计算错误(?:... 将其想象为笑脸),那么返回a.title &lt;=&gt; b.title 的结果。

    否则,如果名称比较的结果不为 0,则在 Elvis 运算符中正确计算并返回该值。

    这一切都考虑到您可以将空值与字符串进行比较,并且'any string' &gt; null 始终成立(这与说'any string' &lt;=&gt; null == 1 相同)。

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

    我希望那是您正在寻找的。如果您期望排序元素的不同顺序,请随时在 cmets 中澄清它:)

    更新

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

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

    【讨论】:

    • 如果对象没有name 属性,此解决方案将引发异常,但问题是“根据“名称”对其进行排序如果存在
    • @Don 可能。该问题未指定“不存在”是否意味着该属性为空(或空字符串)或没有具有该名称的属性。所以我选择了最简单的路线=D
    • 我想您可以将“如果存在”解释为“不为空”,这对您来说非常方便:)
    【解决方案2】:

    您可以使用Comparator 对集合进行排序。

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

    【讨论】:

      【解决方案3】:

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

      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)
      

      【讨论】:

        猜你喜欢
        • 2015-08-18
        • 2011-02-01
        • 2011-08-13
        • 1970-01-01
        • 1970-01-01
        • 2011-05-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多