Руби хэш-перестановка - PullRequest
       31

Руби хэш-перестановка

4 голосов
/ 04 октября 2011

Есть ли какой-нибудь быстрый способ получить (случайную) перестановку заданного хеша?Например, для массивов я могу использовать метод sample , как в

ruby-1.9.2-p180 :031 > a = (1..5).to_a
 => [1, 2, 3, 4, 5] 
ruby-1.9.2-p180 :032 > a.sample(a.length)
 => [3, 5, 1, 2, 4] 

Для хэшей я могу использовать тот же метод для ключей хешей и создать новый хэш с

ruby-1.9.2-p180 :036 > h = { 1 => 'a', 2 => 'b', 3 => 'c' }
 => {1=>"a", 2=>"b", 3=>"c"} 
ruby-1.9.2-p180 :037 > h.keys.sample(h.length).inject({}) { |h2, k| h2[k] = h[k]; h2 }
 => {3=>"c", 2=>"b", 1=>"a"} 

но это так ужасно.Есть ли какой-нибудь «примерный» метод для хэшей, который может избежать всего этого кода?

Обновление Как отметил @Michael Kohl в комментариях, этот вопрос имеет смысл только для ruby ​​1.9.x.Поскольку в 1.8.x хэш неупорядочен, сделать это невозможно.

Ответы [ 3 ]

9 голосов
/ 04 октября 2011

Небольшое уточнение му - слишком короткий ответ:

h = Hash[h.to_a.shuffle]
4 голосов
/ 04 октября 2011

Просто добавьте to_a и Hash[] к вашей версии массива, чтобы получить версию Hash:

h = Hash[h.to_a.sample(h.length)]

Например:

>> h = { 1 => 'a', 2 => 'b', 3 => 'c' }
=> {1=>"a", 2=>"b", 3=>"c"}
>> h = Hash[h.to_a.sample(h.length)]
=> {2=>"b", 1=>"a", 3=>"c"}
0 голосов
/ 06 декабря 2017

Вам действительно нужно перемешать или вам просто нужен способ доступа / итерации по случайному ключу?

В противном случае, возможно, более дешевым решением было бы перестановка ключей хеша и доступ к вашим элементам на основе перестановки этих ключей хеша

h = your_hash
shuffled_hash_keys = hash.keys.shuffle

shuffled_hash_keys.each do |key|
  # do something with h[key]
end

Я полагаю (но понадобилось бы доказательство с эталоном), что это избавляет от необходимости / стоимости для создания совершенно нового хэша и, вероятно, более эффективно, если у вас большие хэши (вам нужно только заплатить стоимость перестановки массива) )

...