2015-10-19 2 views
2

У меня есть ссылочный хэш всех возможных рангов, которая выглядит так:Определите, существуют ли соседи?

hash = { 
    bronze: 0, 
    silver: 1, 
    gold: 2, 
    platinum: 3, 
    diamond: 4 
} 

Я получаю данное звание, и целый ряд других существующих рангов, и мне нужно, чтобы определить, существует ли "соседи для данного ранг. Постараюсь пример:

given_rank = 'gold' 
existing_ranks = ['silver', 'platinum'] 

Это должно вернуть true - серебро непосредственно под золото и платина непосредственно выше - как соседи присутствуют.

given_rank = 'gold' 
existing_ranks = ['silver', 'diamond'] 

Это должно вернуть false - платина отсутствует на верхней стороне

Вот что я сейчас:

user_rank = hash[given_rank] 
higher = hash.invert[user_rank + 1] 
lower = hash.invert[user_rank - 1] 

if existing_ranks.include?(higher) && existing_ranks.include?(lower) 
    # do something 
else 
    # do another thing 
end 

Есть более эффективный/эффективный/рубиновый способ решить эту проблему ?

ответ

2

Используя тривиальное математическую зависимость между последовательными индексами, вы можете написать:

n1, n2 = hash.values_at(*existing_ranks) 
are_neighbors = (n1 - n2).abs == 2 && hash[given_rank] == (n1 + n2)/2 
+1

Вы имеете в виду '(n2 - n1) .abs == 2'? – nsave

+0

@nsave: хорошая точка, обновлено. – tokland

0

Немного советов: работа с символами вместо строк для ваших рядов.

hash = { 
    bronze: 0, 
    silver: 1, 
    gold: 2, 
    platinum: 3, 
    diamond: 4 
} 
given_rank = :gold 
existing_ranks = [:silver, :platinum] 

is_neighbor = existing_ranks.map{ |rank| (hash[rank] - hash[given_rank]).abs }.uniq == [1] 

Теперь вы shoulod есть is_neighbor == true, если оба ваших existing_ranks сосед вашего заданного ранга

0
def correct_ordering?(hash, existing_ranks, given_rank) 
    hash.values_at(*existing_ranks).sort == [hash[given_rank]-1, hash[given_rank]+1] 
end 

existing_ranks = [:silver, :platinum] 

correct_ordering?(hash, existing_ranks, :gold) #=> true 
correct_ordering?(hash, existing_ranks, :diamond) #=> false 
0

Если ключ не найден в хеше, то результат nil. Просто удалите nil, чтобы получить действительный сосед (ы)

hash = { 
    bronze: 0, 
    silver: 1, 
    gold: 2, 
    platinum: 3, 
    diamond: 4 
} 

given_rank = 'gold' 
existing_ranks = ['silver', 'platinum'] 

ranks = hash.invert 
r = hash[given_rank.to_sym] 
# compact method deletes nil values: 
p existing_ranks.map(&:to_sym) == [ranks[r-1], ranks[r+1]].compact # => true 
Смежные вопросы