Sorting an array of arrays in Ruby

后端 未结 4 1924
佛祖请我去吃肉
佛祖请我去吃肉 2021-02-07 00:07

I have an array of arrays like so:

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


        
相关标签:
4条回答
  • 2021-02-07 00:21

    You can't use <=> with nil.

    Your code should be something like this:

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

    This will put the sub-arrays that have no element of index 4 at the beginning of the result. To do it the other way around, swap -1 with 1.

    You could also use sort_by instead of sort. I think this has been introduced in Ruby 1.8.7 (so it might not work if you are using an older version). It goes something like:

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

    This will treat sub-arrays with no 4th element as if it was 0. Change this constant to suit you.

    EDIT:

    After you adjusted the input, it is now clear you were very close to the right answer. Your code should have been:

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

    Or simple (assuming Ruby 1.8.7 or more):

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

    In both cases, the variables a and b will contain elements of the original array, this is why you can directly access an element in any position (and you don't need something like a[][4], which is incorrect Ruby syntax).

    0 讨论(0)
  • 2021-02-07 00:25

    The 4th element is actually at index 3, which means you would do it like this:

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

    If you really want to sort the elements at index 4 (which doesn't exist for the first element of all_devices), then you need to add comparison to the NilClass first:

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

    This will sort nil to the end. Change the return value of <=> to -1 to sort them to the front.

    0 讨论(0)
  • 2021-02-07 00:27

    sort_by

    Instead of using spaceship operator (<=>) give a try to sort_by

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

    Though if you know that the forth element is the last one, you can use el.last too in the block.

    Ruby docs: Enumerable#sort_by

    0 讨论(0)
  • 2021-02-07 00:34

    I know the question has been answered, and I'm not going to address it now, but..

    Are you sure an array would be the best fit for that data? I'm talking about these data elements: ["name1", "type1", ["A", "N", "N"], ["Attribute", "device_attribute"], 9]

    Seems like a Struct or something might be more appropriate and manageable for this, and then you can have an array of Structs. Just an idea.

    0 讨论(0)
提交回复
热议问题