Несколько возвращаемых значений с массивами и хешами

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

def some_method
  return [1, 2]
end

[a, b] = some_method # should yield a = 1 and b = 2

Я предполагаю, что это своего рода синтаксический сахар, который предоставляет Ruby. Можем ли мы получить аналогичный результат с хешами, например

def some_method
  return { "a" => 1, "b" => 2 }
end

{"c", "d"} = some_method() # "c" => 1, "d" => 2

Я ищу результат { "c" => 1, "d" => 2 }что, очевидно, не происходит. Есть ли другой способ сделать это? Я знаю, что мы можем вернуть хеш из метода и сохранить его и использовать его так

def some_method
  return {"a" => 1, "b" => 2}
end

hash = some_method()

Просто любопытно, есть ли другой способ, похожий на тот, что с массивами, но с использованием хешей....


Я думаю, что более простой способ поставить вопрос будет...



    # If we have a hash
    hash = {"a" => 1, "b" => 2}

    # Is the following possible
    hash = {2, 3} # directly assigning values to the hash.
    OR
    # another example
    {"c", "d"} = {2, 3} # c and d would be treated as keys and {2, 3} as respective values.

2 ответа

Решение

То, что вы спрашиваете, синтаксически невозможно.

То, чего вы хотите достичь, возможно, но вам придется его кодировать. Один из возможных способов сделать это показан ниже

hash = {"a" => 1, "b" => 2}

# Assign new keys
new_keys = ["c", "d"]
p [new_keys, hash.values].transpose.to_h
#=> {"c"=>1, "d"=>2}

# Assign new values
new_values = [3, 4]
p [hash.keys, new_values].transpose.to_h
#=> {"a"=>3, "b"=>4}

Если вы действительно хотите более простой и понятный способ сделать это, вы можете сделать monkey-patch Hash класс и определить новые методы для манипулирования значениями keys а также values массив. Пожалуйста, имейте в виду, что не стоит связываться с основными классами. В любом случае, возможная реализация показана ниже. Используйте на свой риск.

class Hash
    def values= new_values
        new_values.each_with_index do |v, i|
            self[keys[i]] = v if i < self.size
        end
    end
    def keys= new_keys
        orig_keys = keys.dup
        new_keys.each_with_index do |k, i|
            if i < orig_keys.size
                v = delete(orig_keys[i])
                self[k] = v
                rehash
            end
        end
    end
end

hash = {"a" => 1, "b" => 2}

hash.values = [2,3]
p hash
#=> {"a"=>2, "b"=>3}

hash.keys = ["c", "d"]
p hash
#=> {"c"=>2, "d"=>3}

hash.keys, hash.values = ["x","y"], [9, 10]
p hash
#=> {"x"=>9, "y"=>10}

hash.keys, hash.values = ["x","y"], [9, 10]
p hash
#=> {"x"=>9, "y"=>10}

# *** results can be unpredictable at times ***
hash.keys, hash.values = ["a"], [20, 10]
p hash
#=> {"y"=>20, "a"=>10}

Прежде всего, у вас есть синтаксическая ошибка. Вместо этого:

[a, b] = [1, 2]

вы должны использовать:

a, b = [1, 2]

И если вы хотите использовать подобный синтаксис с хешами, вы можете сделать:

a, b = { "c" => 1, "d" => 2 }.values     # a => 1, b => 2

На самом деле это то же самое, что и версия массива, потому что Hash#values возвращает массив значений хеш-функции в том порядке, в котором они были вставлены в хеш-код (потому что хэши ruby ​​имеют хорошую функцию сохранения их порядка)

Другие вопросы по тегам