在迭代Hash / Array

时间:2015-06-12 15:56:44

标签: ruby

我需要在#each上实现回调。 each的接收者可能同时为ArrayHash。所以,我有一个代码:

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参数。一切只有Array大小2。我注定要坚持使用显式类型检查吗?

1 个答案:

答案 0 :(得分:1)

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

var cloudinary = require("cloudinary");
var CLOUD_API_SECRET = require("../constants.js");

cloudinary.config({
  cloud_name: 'some_cloud',
  api_key: '63789865675995',
  api_secret: CLOUD_API_SECRET
});

router.post('/pic', function(req, res, next) {
  var img = req.body.img;
  cloudinary.uploader.upload(img, function(result) {
  });

  res.status(200).send('ok');

});

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

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

正在使用中:

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