[英]What is the Ruby equivalent of PHP's compact?
Given some local variables , what would be the easiest way to compact
them in Ruby? 给定一些局部变量 ,在Ruby中
compact
它们最简单的方法是什么?
def foo
name = 'David'
age = 25
role = :director
...
# How would you build this:
# { :name => 'David', :age => 25, :role => :director }
# or
# { 'name' => 'David', 'age' => 25, 'role' => :director }
end
In PHP, I can simply do this: 在PHP中,我可以简单地这样做:
$foo = compact('name', 'age', 'role');
I came up with a significant improvement on my original answer. 我的原始答案得到了显着改善。 It is cleaner if you inherit from
Binding
itself. 如果从
Binding
本身继承,它会更清晰。 The to_sym
is there because older versions of ruby have local_variables
as strings. to_sym
就在那里,因为旧版本的ruby将local_variables
作为字符串。
instance method 实例方法
class Binding
def compact( *args )
compacted = {}
locals = eval( "local_variables" ).map( &:to_sym )
args.each do |arg|
if locals.include? arg.to_sym
compacted[arg.to_sym] = eval( arg.to_s )
end
end
return compacted
end
end
usage 用法
foo = "bar"
bar = "foo"
binding.compact( "foo" ) # => {:foo=>"bar"}
binding.compact( :bar ) # => {:bar=>"foo"}
Original answer 原始答案
This is the nearest I could get to a method that behaves like Php's compact
- 这是我能得到的最接近Php
compact
方法的方法 -
method 方法
def compact( *args, &prok )
compacted = {}
args.each do |arg|
if prok.binding.send( :eval, "local_variables" ).include? arg
compacted[arg.to_sym] = prok.binding.send( :eval, arg )
end
end
return compacted
end
example usage 示例用法
foo = "bar"
compact( "foo" ){}
# or
compact( "foo", &proc{} )
Its not perfect though, because you have to pass a proc in. I am open to suggestions about how to improve this. 但它并不完美,因为你必须通过一个过程。我愿意接受如何改进它的建议。
This is a variant on Bungus' answer, but here's a one-liner that is decidedly uglier, but doesn't extend Binding or anything: 这是Bungus回答的一个变种,但是这里的单行是非常丑陋的,但不会扩展Binding或任何东西:
foo = :bar
baz = :bin
hash = [:foo, :baz].inject({}) {|h, v| h[v] = eval(v.to_s); h }
# hash => {:baz=>:bin, :foo=>:bar}
You can also make it look kinda-sorta like a method call by abusing a block binding - again, a variant on Bungus' original answer: 您也可以通过滥用块绑定使其看起来像一个方法调用 - 再次,Bungus的原始答案的变体:
module Kernel
def compact(&block)
args = block.call.map &:to_sym
lvars = block.binding.send(:eval, "local_variables").map &:to_sym
(args & lvars).inject({}) do |h, v|
h[v] = block.binding.send(:eval, v.to_s); h
end
end
end
foo = :bar
baz = :bin
compact {[ :foo, :bar, :baz ]}
# {:foo=>:bar, :baz=>:bin}
(I'll just tell myself that {[..]}
is the trash compactor symbol.) (我只是告诉自己
{[..]}
是垃圾压缩符号。)
If you use the binding_of_caller
gem, you can forgo the proc and explicit binding all together: 如果你使用
binding_of_caller
gem,你可以放弃proc 和显式绑定:
require 'binding_of_caller'
module Kernel
def compact(*args)
lvars = binding.of_caller(1).send(:eval, "local_variables").map &:to_sym
(args.map(&:to_sym) & lvars).inject({}) do |h, v|
h[v] = binding.of_caller(2).send(:eval, v.to_s); h
end
end
end
foo = :bar
baz = :bin
compact :foo, :bar, :baz
# {:foo=>:bar, :baz=>:bin}
Be warned, it's slow. 请注意,它很慢。 In production code, you should probably never attempt to do this and instead just keep a hash of values so the programmer who has to maintain this after you doesn't hunt you down and kill you in your sleep.
在生产代码中,你可能永远不应该尝试这样做,而只是保留一个值的哈希,以便程序员必须在你没有追捕并在睡眠中杀死你之后保持这一点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.