简单的哈希由ruby中的键和值数组合并(使用perl示例)

时间:2021-01-11 21:17:11

In Perl to perform a hash update based on arrays of keys and values I can do something like:

在Perl中,基于键和值数组执行哈希更新,我可以执行以下操作:

@hash{'key1','key2','key3'} = ('val1','val2','val3');

In Ruby I could do something similar in a more complicated way:

在Ruby中,我可以用更复杂的方式做类似的事情:

hash.merge!(Hash[ *[['key1','key2','key3'],['val1','val2','val3']].transpose ])

OK but I doubt the effectivity of such procedure.

好的,但我怀疑这种程序的有效性。

Now I would like to do a more complex assignment in a single line.

现在我想在一行中做更复杂的任务。

Perl example:

Perl示例:

(@hash{'key1','key2','key3'}, $key4) = &some_function();

I have no idea if such a thing is possible in some simple Ruby way. Any hints?

我不知道这种东西是否可以用一些简单的Ruby方式实现。任何提示?

For the Perl impaired, @hash{'key1','key2','key3'} = ('a', 'b', 'c') is a hash slice and is a shorthand for something like this:

对于Perl受损者,@ hash {'key1','key2','key3'} =('a','b','c')是一个哈希切片,是这样的简写:

$hash{'key1'} = 'a';
$hash{'key2'} = 'b';
$hash{'key3'} = 'c';

3 个解决方案

#1


3  

You could redefine []= to support this:

你可以重新定义[] =来支持这个:

class Hash
  def []=(*args)
    *keys, vals = args # if this doesn't work in your version of ruby, use "keys, vals = args[0...-1], args.last"
    merge! Hash[keys.zip(vals.respond_to?(:each) ? vals : [vals])]
  end
end

Now use

现在用

myhash[:key1, :key2, :key3] = :val1, :val2, :val3
# or
myhash[:key1, :key2, :key3] = some_method_returning_three_values
# or even
*myhash[:key1, :key2, :key3], local_var = some_method_returning_four_values

#2


4  

In Ruby 1.9 Hash.[] can take as its argument an array of two-valued arrays (in addition to the old behavior of a flat list of alternative key/value arguments). So it's relatively simple to do:

在Ruby 1.9中,Hash。[]可以将一个二值数组的数组作为其参数(除了替代键/值参数的平面列表的旧行为之外)。这样做比较简单:

mash.merge!( Hash[ keys.zip(values) ] )

I do not know perl, so I'm not sure what your final "more complex assignment" is trying to do. Can you explain in words—or with the sample input and output—what you are trying to achieve?

我不知道perl,所以我不确定你最后的“更复杂的任务”是怎么做的。你能用语言或用样本输入和输出来解释你想要实现的目标吗?

Edit: based on the discussion in @fl00r's answer, you can do this:

编辑:根据@ fl00r的答案中的讨论,你可以这样做:

def f(n)
  # return n arguments
  (1..n).to_a
end

h = {}
keys = [:a,:b,:c]
*vals, last = f(4)
h.merge!( Hash[ keys.zip(vals) ] )
p vals, last, h
#=> [1, 2, 3]
#=> 4
#=> {:a=>1, :b=>2, :c=>3}

The code *a, b = some_array will assign the last element to b and create a as an array of the other values. This syntax requires Ruby 1.9. If you require 1.8 compatibility, you can do:

代码* a,b = some_array将最后一个元素分配给b并创建一个其他值的数组。这种语法需要Ruby 1.9。如果您需要1.8兼容性,您可以:

vals = f(4)
last = vals.pop
h.merge!( Hash[ *keys.zip(vals).flatten ] )

#3


1  

you can do this

你可以这样做

def some_method
  # some code that return this:
  [{:key1 => 1, :key2 => 2, :key3 => 3}, 145]
end

hash, key = some_method
puts hash
#=> {:key1 => 1, :key2 => 2, :key3 => 3}
puts key
#=> 145

UPD

UPD

In Ruby you can do "parallel assignment", but you can't use hashes like you do in Perl (hash{:a, :b, :c)). But you can try this:

在Ruby中你可以做“并行赋值”,但你不能像在Perl中那样使用哈希(hash {:a,:b,:c))。但你可以试试这个:

hash[:key1], hash[:key2], hash[:key3], key4 = some_method

where some_method returns an Array with 4 elements.

some_method返回一个包含4个元素的数组。

#1


3  

You could redefine []= to support this:

你可以重新定义[] =来支持这个:

class Hash
  def []=(*args)
    *keys, vals = args # if this doesn't work in your version of ruby, use "keys, vals = args[0...-1], args.last"
    merge! Hash[keys.zip(vals.respond_to?(:each) ? vals : [vals])]
  end
end

Now use

现在用

myhash[:key1, :key2, :key3] = :val1, :val2, :val3
# or
myhash[:key1, :key2, :key3] = some_method_returning_three_values
# or even
*myhash[:key1, :key2, :key3], local_var = some_method_returning_four_values

#2


4  

In Ruby 1.9 Hash.[] can take as its argument an array of two-valued arrays (in addition to the old behavior of a flat list of alternative key/value arguments). So it's relatively simple to do:

在Ruby 1.9中,Hash。[]可以将一个二值数组的数组作为其参数(除了替代键/值参数的平面列表的旧行为之外)。这样做比较简单:

mash.merge!( Hash[ keys.zip(values) ] )

I do not know perl, so I'm not sure what your final "more complex assignment" is trying to do. Can you explain in words—or with the sample input and output—what you are trying to achieve?

我不知道perl,所以我不确定你最后的“更复杂的任务”是怎么做的。你能用语言或用样本输入和输出来解释你想要实现的目标吗?

Edit: based on the discussion in @fl00r's answer, you can do this:

编辑:根据@ fl00r的答案中的讨论,你可以这样做:

def f(n)
  # return n arguments
  (1..n).to_a
end

h = {}
keys = [:a,:b,:c]
*vals, last = f(4)
h.merge!( Hash[ keys.zip(vals) ] )
p vals, last, h
#=> [1, 2, 3]
#=> 4
#=> {:a=>1, :b=>2, :c=>3}

The code *a, b = some_array will assign the last element to b and create a as an array of the other values. This syntax requires Ruby 1.9. If you require 1.8 compatibility, you can do:

代码* a,b = some_array将最后一个元素分配给b并创建一个其他值的数组。这种语法需要Ruby 1.9。如果您需要1.8兼容性,您可以:

vals = f(4)
last = vals.pop
h.merge!( Hash[ *keys.zip(vals).flatten ] )

#3


1  

you can do this

你可以这样做

def some_method
  # some code that return this:
  [{:key1 => 1, :key2 => 2, :key3 => 3}, 145]
end

hash, key = some_method
puts hash
#=> {:key1 => 1, :key2 => 2, :key3 => 3}
puts key
#=> 145

UPD

UPD

In Ruby you can do "parallel assignment", but you can't use hashes like you do in Perl (hash{:a, :b, :c)). But you can try this:

在Ruby中你可以做“并行赋值”,但你不能像在Perl中那样使用哈希(hash {:a,:b,:c))。但你可以试试这个:

hash[:key1], hash[:key2], hash[:key3], key4 = some_method

where some_method returns an Array with 4 elements.

some_method返回一个包含4个元素的数组。