2009-07-28 77 views
19

我有陣列的像這樣的數組:排序數組的數組中的Ruby

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

我想的第四元件上的整個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/

我想象我失去了一些東西rubyish使這很容易。

回答

22

您不能使用<=>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中引入(所以如果您使用的是舊版本,它可能不起作用)。它類似於:

​​

這將處理沒有第四個元素的子數組,就好像它是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語法)。

+0

當然,我忽略了device_array的第0個元素的第4個元素。不應該有任何零對象。 – 2009-07-28 15:04:03

+0

在這種情況下,您唯一的問題是使用'a [] [4]'而不是'a [4]'。 'a [] [4]'不是有效的Ruby語法。 – 2009-07-28 15:09:14

2

第四元素實際上是在指數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到底。將<=>的返回值更改爲-1,將它們排序到前面。

+0

這種方法最終可能會使捕捉bug變得更難;因爲它可以讓代碼中的任何地方與'nil'進行比較。它應該明智地使用。 – 2009-07-28 15:07:59

2

我知道這個問題已經回答了,我不會現在要解決這個問題,但..

確定一個數組將是數據最適合?我正在談論這些數據元素:[「name1」,「type1」,[「A」,「N」,「N」],[「Attribute」,「device_attribute」],9]

似乎一個Struct或其他東西可能更合適和可管理,然後你可以有一個Structs數組。只是一個想法。