2015-04-23 119 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