【问题标题】:Sorting an array of arrays in Ruby在 Ruby 中对数组进行排序
【发布时间】:2009-07-28 14:52:23
【问题描述】:

我有一个这样的数组:

irb(main):028:0> device_array
=> [["name1", "type1", ["A", "N", "N"], ["Attribute", "device_attribute"], 9], ["name2","type2", ["A", "N", "N"], ["Attribute", "device_attribute"], 7]]

我想在第 4 个元素上对整个 device_array 进行排序。

我试过了

AllDevicesController.all_devices.sort do | a,b |
  for i in 0..(AllDevicesController.all_devices.length - 1) do
    a[i][4] <=> b[i][4]
  end
end

我也试过了:

AllDevicesController.all_devices.sort do | a,b |
  a[][4] <=> b[][4]
end

这两种方法都没有奏效。

我以此作为参考: http://ariejan.net/2007/01/28/ruby-sort-an-array-of-objects-by-an-attribute/

我想我错过了一些使这变得非常容易的红宝石。

【问题讨论】:

    标签: ruby arrays


    【解决方案1】:

    您不能将&lt;=&gt;nil 一起使用。

    你的代码应该是这样的:

    AllDevicesController.all_devices.sort do |a, b|
      a[4].nil? ? -1 : b[4].nil? ? 1 : a[4] <=> b[4]
    end
    

    这会将没有索引为 4 的元素的子数组放在结果的开头。反过来,将-11 交换。

    您也可以使用sort_by 代替sort。我认为这已在 Ruby 1.8.7 中引入(因此如果您使用的是旧版本,它可能无法正常工作)。它是这样的:

    AllDevicesController.all_devices.sort_by { |e| e.nil? ? 0 : e[4] }
    

    这会将没有第 4 个元素的子数组视为 0。更改此常数以适合您。

    编辑:

    调整输入后,现在很明显您非常接近正确答案。您的代码应该是:

    AllDevicesController.all_devices.sort do |a, b|
      a[4] <=> b[4]
    end
    

    或者简单(假设 Ruby 1.8.7 或更高版本):

    AllDevicesController.all_devices.sort_by { |e| e[4] }
    

    在这两种情况下,变量ab 将包含原始数组的元素,这就是为什么您可以直接访问任何位置的元素(并且您不需要像a[][4] 这样的东西,它是不正确的 Ruby 语法)。

    【讨论】:

    • 我当然遗漏了 device_array 的第 0 个元素的第 4 个元素。不应该有任何 nil 对象。
    • 在这种情况下,您唯一的问题是使用a[][4] 而不是a[4]a[][4] 不是有效的 Ruby 语法。
    【解决方案2】:

    sort_by

    不要使用宇宙飞船操作符(&lt;=&gt;)试试sort_by

    device_array.sort_by { |el| el[4] }
    

    如果你知道第四个元素是最后一个,你也可以在块中使用el.last

    Ruby 文档:Enumerable#sort_by

    【讨论】:

      【解决方案3】:

      第 4 个元素实际上在索引 3 处,这意味着您可以这样做:

      all_devices.sort do |a, b|
        a[3] <=> b[3]
      end
      

      如果你真的想对索引 4 处的元素进行排序(all_devices 的第一个元素不存在),那么你需要先添加对 NilClass 的比较:

      class NilClass
        def <=> (other)
          1
        end
      end
      
      all_devices.sort do |a, b|
        a[4] <=> b[4]
      end
      

      这会将nil 排序到最后。将&lt;=&gt;的返回值改为-1,将它们排在最前面。

      【讨论】:

      • 这种方法最终会使捕捉错误变得更加困难;因为它允许在代码中的任何地方与nil 进行比较。应该明智地使用它。
      【解决方案4】:

      我知道这个问题已经得到解答,我现在不打算解决它,但是..

      您确定数组最适合该数据吗?我说的是这些数据元素:["name1", "type1", ["A", "N", "N"], ["Attribute", "device_attribute"], 9]

      看起来像 Struct 或者更合适和更易于管理的东西,然后你可以拥有一个结构数组。只是一个想法。

      【讨论】:

        猜你喜欢
        • 2012-11-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-07
        • 1970-01-01
        相关资源
        最近更新 更多