3

两个大小相等的集合,例如

u = :a, :b, :c
v = 1, 2, 3

可以很容易地拉上拉链:

u.map.with_index { |e, i| [e, v[i] ] }

但是有#zip方法的时候为什么要麻烦:

u.zip v

同样,它们可以很容易地压缩成哈希:

Hash[ u.zip v ]

我的问题是,Ruby 核心、stdlib 或任何著名的 gem 是否有标准方法来执行这种频繁的操作?我设想是这样的:

u.hashzip v #=> { a: 1, b: 2, c: 3 }
u.hashzip &:to_s #=> { a: "a", b: "b", c: "c" }
4

2 回答 2

2

Hash[u.zip(v)]是我见过的将两个大小相等的数组转换为哈希的最简洁和常见的习惯用法。比较它Hash.combine

require 'benchmark'
require 'pp'

# From:
#     http://rubydoc.info/gems/hash-utils/2.1.2/Hash#combine-class_method
class Hash
  def self.combine(keys, values)
    result = {}
    keys.each_index do |i|
      result[keys[i]] = values[i]
    end

    return result
  end
end

def zip_method(a, b)
  Hash[a.zip(b)]
end

ALPHA = ('a' .. 'z').to_a * 25
NUMERIC = (0 .. 25).to_a * 25
N = 10_000

puts "N = #{ N }"
puts "Ruby version = " + `ruby -v`

pp Hash.combine(%w[a b c], [1, 2, 3])
pp Hash[%w[a b c].zip([1, 2, 3])]
pp zip_method(%w[a b c], [1, 2, 3])

Benchmark.bm(10) do |x|
  x.report('zip') { N.times { Hash[ALPHA.zip(NUMERIC)] }}
  x.report('zip_method') { N.times { zip_method(ALPHA, NUMERIC) }}
  x.report('combine') { N.times { Hash.combine(ALPHA, NUMERIC) }}
end

有了这些结果:

N = 10000
Ruby 版本 = ruby​​ 2.0.0p247(2013-06-27 修订版 41674)[x86_64-darwin12.4.0]
{"a"=>1, "b"=>2, "c"=>3}
{"a"=>1, "b"=>2, "c"=>3}
{"a"=>1, "b"=>2, "c"=>3}
                 用户系统总真实
拉链 1.990000 0.010000 2.000000 (1.993747)
zip_method 1.980000 0.000000 1.980000 (1.990298)
结合 2.130000 0.000000 2.130000 ( 2.133492)

我补充说zip_method,看看调用该方法会有什么不同。奇怪的是,它没有任何作用。我可能错过了一些东西。

这种问题已经存在了一段时间:http ://www.ruby-forum.com/topic/125944

于 2013-07-03T05:40:13.057 回答
0

鉴于这里温和鼓励回答自己的问题,我现在已经到了将“hashzip”方法作为我的y_supportgem 的一部分,重载>>运算符的地步:

require 'y_support/core_ext/array'

x = :a, :b, :c
y = 1, 2, 3

x >> y
#=> {:a=>1, :b=>2, :c=>3}
于 2014-02-22T13:36:23.293 回答