2014-10-08 59 views
0

我需要創建一個將哈希和數字作爲參數的方法,並按年齡返回一個新的寵物名稱數組。使用Ruby在特定數字的哈希中查找對象使用Ruby

my_family_pets_ages = {"Evi" => 6, "Hoobie" => 3, "George" => 12, "Bogart" => 4, "Poly" => 4, 
    "Annabelle" => 0, "Ditto" => 3} 

我的,我有兩個解決我的問題:

def my_hash_finding_method(source, thing_to_find) 
    source.select {|k,v| v.include? thing_to_find} 
end 
my_hash_finding_method(my_family_pets_ages, 3) 

def my_hash_finding_method(source, thing_to_find) 
    source.select {|k,v| v.has_value? thing_to_find} 
end 
my_hash_finding_method(my_family_pets_ages, 3) 

當我運行我的程序與IRB或者在命令行中,我得到:

my_solution.rb:15:in `block in my_hash_finding_method': 
undefined method `include?'for 6:Fixnum (NoMethodError) 

爲什麼include?未定義的方法?當我使用has_value? 時,它也會說同樣的事情我可以使用過時的Ruby版本嗎?我在2.0.0上?

更新: 這是我想出的新解決方案,它似乎工作。

def my_hash_finding_method(source, thing_to_find) 
    num_array = [] 
    source.each do |k,v| 
     if v == thing_to_find 
     num_array << k 
     end 
    end 
    print num_array.sort 
end 
+1

這氣味像功課或某些類型的任務。版本2.0已過時,因爲當前版本的Ruby是2.1.3,但我懷疑這是問題所在。 (雖然你應該升級自2.0以來是越野車。) – 2014-10-08 22:20:51

回答

0

我會變得有點co because,因爲這聽起來像家庭作業,但是你知道k和v在那個區塊裏代表什麼?

錯誤消息是一個很大的提示。它告訴你,你試着發送消息給不是哈希的東西,當然它沒有爲哈希定義的方法。你在Fixnum上調用include?

(檢查Ruby documentation for Hash select知道發生了什麼實際上是被放在那裏,如果你想知道更多。)

簡而言之:塊內,你與變量,其價值得到由哈希集合,而不是操作上的工作哈希本身。你需要根據這些進行檢查。

0

這兩種方法在默認情況下不存在,至少不是您使用的對象。

v.include? 

會工作,如果v是一個枚舉的,如哈希或數組,而是它是一個數值,因爲它是針對特定鍵的值,並沒有定義的方法。對於v.has_value?也是如此。 v仍然是該特定鍵的價值。如果您使用|k,v|,則select將按鍵和值作爲單獨參數傳入。 (以Ruby的方式,如果您使用單個變量,它們將是一個二元陣列。)

爲了幫助您學習如何自助,Ruby在命令行中包含了ri命令。你可以輸入ri has_value?來查看Ri是否知道任何類的實現。在其他結果是:

 
=== Implementation from Hash 
------------------------------------------------------------------------------ 
    hsh.has_value?(value) -> true or false 

------------------------------------------------------------------------------ 

Returns true if the given value is present for some key in hsh. 

    h = { "a" => 100, "b" => 200 } 
    h.has_value?(100) #=> true 
    h.has_value?(999) #=> false 

沿着相同的線路,爲include?

 
=== Implementation from Hash 
------------------------------------------------------------------------------ 
    hsh.include?(key) -> true or false 

------------------------------------------------------------------------------ 

Returns true if the given key is present in hsh. 

    h = { "a" => 100, "b" => 200 } 
    h.has_key?("a") #=> true 
    h.has_key?("z") #=> false 

在任一情況下,數字將不具有這些方法,這是在錯誤的來源。


將沿東西此項工作的線路?

def my_hash_finding_method(source, thing_to_find) 
    source.select {|k,v| 
     if v == thing_to_find then return source[k] end 
    } 
    end 

這已經很接近,但return不屬於那裏,將導致只有一個值,即使有現有的多個值。考慮這個:

MY_FAMILY_PETS_AGES = { 
    "Evi"  => 6, 
    "Hoobie" => 3, 
    "George" => 12, 
    "Bogart" => 4, 
    "Poly"  => 4, 
    "Annabelle" => 0, 
    "Ditto"  => 3 
} 

def my_hash_finding_method(source, thing_to_find) 
    source.select{ |k, v| v == thing_to_find } 
end 

my_hash_finding_method(MY_FAMILY_PETS_AGES, 3) # => {"Hoobie"=>3, "Ditto"=>3} 

如果你想接收排序結果,那麼,爲什麼?當前Rubies中的select將返回一個散列,並且散列不會從排序中受益,因爲它們基本上是隨機訪問對象,導致無論散列是排序還是未排序,訪問值的速度都一樣快。

如果你想返回鍵/值對的有序數組,那麼這就是做這件事:

def my_hash_finding_method(source, thing_to_find) 
    source.select{ |k, v| v == thing_to_find }.sort_by{ |k, v| k } 
end 

my_hash_finding_method(MY_FAMILY_PETS_AGES, 3) # => [["Ditto", 3], ["Hoobie", 3]] 

如果你只想要寵物的名稱,而不是姓名和年齡,只有抓住由select返回鍵:

def my_hash_finding_method(source, thing_to_find) 
    source.select{ |k, v| v == thing_to_find }.keys.sort 
end 

my_hash_finding_method(MY_FAMILY_PETS_AGES, 3) # => ["Ditto", "Hoobie"] 

注意,在該解決方案從select返回一個哈希我使用sort_by,並在最後一個常規sortsort適用於數值和字符/字符串等已具有已建立順序的值,但在使用塊訪問傳入的值內部的屬性進行排序時效率不高,因爲它必須執行大量冗餘計算以確定如何排序傳入值。 sort_by是一個有趣的算法,通常被稱爲Schwartzian Transform,它計算每個條目被排序一次的值,記住它,按該值排序,然後以正確的順序排出相關項目。這會導致非常高效的排序,如果排序後的值不易獲取,則可以大大優於常規排序。

我做了差異的基準以及如何在「Sorting an array in descending order in Ruby」中快速執行降序排序,因此花一些時間查看所選問題的答案。

+0

@the_Tin_Man,我明白你的意思是通過調用.include?在一個枚舉。這件作品會有什麼? def my_hash_finding_method(source,thing_to_find) source.select {| k,v | if v == thing_to_find then return source [k] end} end – Lasonic 2014-10-08 23:24:33

0

你是否試圖按值分組哈希?

然後嘗試:

pets.group_by{|k,v| v} 

如果你想用一個值只返回項目的數組:

pets.map { |k, v| v == value }