Я хочу переименовать хэш-ключ. Этот:
myhash[preferred_name] = myhash.delete old_name
вставляет новую пару значений ключа в последний индекс моего хэша. Есть ли способ переименовать хеш без добавления нового?
да, это работает, но он вставит новый хеш в последний индекс, который мне не нравится. Я хочу сохранить порядок пар "ключ-значение" в моем хэше
Я не могу найти его легко, возможно, можно было бы перебрать и отбросить все параметры в новый хэш и изменить один с помощью select, но это очень быстро испортится. На всякий случай, вот методы, доступные для Hash docs.ruby-lang.org/en/2.0.0/Hash.html
Я второй ответ @Stefen, при условии, что нет необходимости поддерживать версии Ruby до 2.5, когда Хешируйте # transform_keys! дебютировал. Если более ранние версии должны поддерживаться, вот один способ (который не создает новый хэш), расширение подхода, упомянутого OP.
h = { foo: 1, bar: 2, baz: 3 }
h.keys.each { |k| h[k == :bar ? :qux : k] = h.delete(k) }
#=> [:foo, :bar, :baz]
h #=> {:foo=>1, :qux=>2, :baz=>3}
Обратите внимание, что перечислители Хэш # each_key и Хэш # каждый нельзя использовать, потому что ключи удаляются во время итерации.
Другой выбор следующий.
keys = h.keys
keys[keys.index(:bar)] = :qux
h.replace(keys.zip(h.values).to_h)
#=> {:foo=>1, :qux=>2, :baz=>3}
myhash.to_a.each { |a| a[0] = preferred_name if a[0] == old_name }.to_h
Или:
h.map { |k, v| [k == old_name ? preferred_name : k, v] }.to_h
К сожалению, оба решения будут сканировать всю структуру даже после того, как совпадение будет найдено, поэтому, если в вашем хэше много записей, вы можете предпочесть один из других вариантов.
Когда я пробую ваше существующее решение, оно работает, как ожидалось. Один ключ удаляется, а значению дается новое имя. Какую версию Ruby вы используете?