加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby – 在迭代Hash / Array时区分{k :: v}与[:k,:v]

发布时间:2020-12-17 02:08:08 所属栏目:百科 来源:网络整理
导读:我需要在#each上实现回调.每个接收器可能都是Array和Hash.所以,我有一个代码: receiver.each do |k,v| case receiver when Hash then puts "#{k} = #{v}" when Array then puts "[#{k},#{v}]" endend 但接收器的检查是蹩脚的.有没有办法接收/解释一个代码块
我需要在#each上实现回调.每个接收器可能都是Array和Hash.所以,我有一个代码:

receiver.each do |k,v|
  case receiver
  when Hash then puts "#{k} = #{v}"
  when Array then puts "[#{k},#{v}]"
  end
end

但接收器的检查是蹩脚的.有没有办法接收/解释一个代码块参数[s],以清楚地区分以下情况:

{ a: 1,b: 2 }

[[:a,1],[:b,2]]

我尝试过括号,单个参数,splatted参数.一切都只是得到一个大小为2的数组.我注定要坚持显式类型检查?

解决方法

您可以做的最好的事情是从循环中获取类型检查:

def foo(receiver)
  format = receiver.is_a?(Array) ? "[%s,%s]" : "%s = %s"
  receiver.each do |k_v|
    puts format % k_v
  end
end

>见String#%

如果你想在每个块中告诉键/值对是来自数组还是哈希,你必须求助于猴子修补.它可以做到,但它非常糟糕:

class Hash
  orig_each = instance_method(:each)
  define_method(:each) do |&block|   
    orig_each.bind(self).call do |kv|
      def kv.from_hash?
        true
      end
      def kv.from_array?
        false
      end
      block.call(kv)
    end
  end
end

class Array
  orig_each = instance_method(:each)
  define_method(:each) do |&block|   
    orig_each.bind(self).call do |kv|
      def kv.from_hash?
        false
      end
      def kv.from_array?
        true
      end
      block.call(kv)
    end
  end
end

正在使用:

e = {a: 1,b: 2}
e.each do |kv|
  p [kv.from_hash?,kv.from_array?,kv]
end
# => [true,false,[:a,1]]
# => [true,2]]

e = [[:a,2]]
e.each do |kv|
  p [kv.from_hash?,kv]
end
# => [false,true,1]]
# => [false,2]]

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读