2015-04-23 194 views
1

我有這個散列:如何從哈希中獲取下一個哈希元素?

HASH = { 
    'x' => { :amount => 0 }, 
    'c' => { :amount => 5 }, 
    'q' => { :amount => 10 }, 
    'y' => { :amount => 20 }, 
    'n' => { :amount => 50 }  
} 

我怎樣才能得到下一個最高amount從哈希的關鍵?

例如,如果我提供x,則應該返回c。如果沒有更高的金額,那麼應該返還金額最低的金鑰。這意味着當我提供n時,將返回x

任何人都可以幫忙嗎?

+0

您的散列是否已按數量排序? –

+0

是的。但是我讀了一些不能在Ruby中排序哈希的地方。不過,我可能是錯的。 – Tintin81

+2

@ Tintin81你可以在ruby中對散列進行排序。哈希使用可枚舉模塊給出'sort'和'sort_by'方法 –

回答

3

我會使用這樣的:

def next_higher(key) 
    amount = HASH[key][:amount] 
    sorted = HASH.sort_by { |_, v| v[:amount] } 
    sorted.find(sorted.method(:first)) { |_, v| v[:amount] > amount }.first 
end 

next_higher "x" #=> "c" 
next_higher "n" #=> "x" 
+0

這個效果很好。謝謝。 – Tintin81

2

我會做這樣的事情:

def find_next_by_amount(hash, key) 
    sorted = hash.sort_by { |_, v| v[:amount] } 
    index_of_next = sorted.index { |k, _| k == key }.next 
    sorted.fetch(index_of_next, sorted.first).first 
end 

find_next_by_amount(HASH, 'x') 
# => "c" 

find_next_by_amount(HASH, 'n') 
# => "x" 
+0

這工作就像一個魅力。謝謝。除非有人想出更短的版本,否則我會將其標記爲正確的答案。 – Tintin81

+2

請注意,即使金額相同,也會始終返回下一個鍵。 – Stefan

1

類似的東西:

def next(key) 
    amount = HASH[key][:amount] 
    kv_pairs = HASH.select{ |k, v| v[:amount] > amount } 
    result = kv_pairs.empty? ? HASH.first.first : kv_pairs.min_by{ |k, v| v}.first  
end 

我很好奇,你爲什麼會想這樣的事情?也許有更好的解決方案的基礎任務。

編輯:認識到哈希沒有必要按金額排序,適用於未分類哈希的代碼。

+1

@ toro2k你得到一個'SyntaxError'因爲你正在調用['next'語句](http://ruby-doc.org/core-2.2.2/doc/syntax/control_expressions_rdoc.html#label-next+Statement )在循環之外,不是因爲方法名稱。調用'self.next(0)'或'send(:next,0)'會起作用,但當然,沒有理智的開發人員會使用'next'作爲方法名稱:-) – Stefan

+0

等待,您的評論在哪裏? – Stefan

+0

@Stefan我意識到,在你發佈你的內容之前,它並沒有完全正確,我刪除了它。 – toro2k

1

一種方法:(如果HASH的鑰匙已經在正確的順序,這僅僅是A = HASH.keys

A = HASH.sort_by { |_,h| h[:amount] }.map(&:first) 
    #=> ['x', 'c', 'q', 'y', 'n'] 

def next_one(x) 
    A[(A.index(x)+1)%A.size] 
end 

next_one 'x' #=> 'c' 
next_one 'q' #=> 'y' 
next_one 'n' #=> 'x' 

或者,您可以創建一個散列而不是方法:

e = A.cycle 
    #=> #<Enumerator: ["x", "c", "q", "y", "n"]:cycle> 
g = A.size.times.with_object({}) { |_,g| g.update(e.next=>e.peek) } 
    #=> {"x"=>"c", "c"=>"q", "q"=>"y", "y"=>"n", "n"=>"x"} 
+0

這看起來也很酷。謝謝。我開始意識到我的問題有很多答案。 – Tintin81