简体   繁体   English

简单的 hash 通过 ruby 中的键和值数组合并(以 perl 为例)

[英]simple hash merge by array of keys and values in ruby (with perl example)

In Perl to perform a hash update based on arrays of keys and values I can do something like:在 Perl 执行基于 arrays 的键和值的 hash 更新我可以执行以下操作:

@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.我不知道这样的事情是否可以通过一些简单的 Ruby 方式实现。 Any hints?有什么提示吗?

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 切片,是这样的简写:

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

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).在 Ruby 1.9 Hash.[]中,可以将二值 arrays 数组作为其参数(除了替代键/值的平面列表的旧行为)。 So it's relatively simple to do:所以做起来比较简单:

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.我不知道 perl,所以我不确定您最终的“更复杂的任务”要做什么。 Can you explain in words—or with the sample input and output—what you are trying to achieve?你能用文字或示例输入和输出来解释你想要实现的目标吗?

Edit : based on the discussion in @fl00r's answer, you can do this:编辑:根据@fl00r's answer中的讨论,您可以这样做:

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.代码*a, b = some_array会将最后一个元素分配给b并创建a作为其他值的数组。 This syntax requires Ruby 1.9.此语法需要 Ruby 1.9。 If you require 1.8 compatibility, you can do:如果您需要 1.8 兼容性,您可以执行以下操作:

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

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

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) ).在 Ruby 中,您可以执行“并行分配”,但不能像在 Perl 中那样使用散列( hash{:a, :b, :c) )。 But you can try this:但是你可以试试这个:

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

where some_method returns an Array with 4 elements.其中some_method返回一个包含 4 个元素的数组。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM