Ruby 如果散列中只有一个特定键具有true值(所有其他值都为false),如何返回true
例如:Ruby 如果散列中只有一个特定键具有true值(所有其他值都为false),如何返回true,ruby,hash,Ruby,Hash,例如: options = { fight: true, use_item: false, run_away: false, save_game: false } 我想要一个布尔表达式,其计算结果为trueiff only:fight为true,其余为false(如上所示) 我可以把它拼凑起来,但我正在努力训练自己写出更优雅的ruby。谢谢 编辑:黑客是: (options[:fight]==true&&options.delete(:fight).values.all{x | x})
options = { fight: true,
use_item: false,
run_away: false,
save_game: false }
我想要一个布尔表达式,其计算结果为true
iff only:fight
为true
,其余为false
(如上所示)
我可以把它拼凑起来,但我正在努力训练自己写出更优雅的ruby。谢谢
编辑:黑客是:
(options[:fight]==true&&options.delete(:fight).values.all{x | x})
或
假设所有值都是严格的布尔值,则其简单程度如下:
options == {fight: true, use_item: false, run_away: false, save_game: false}
我认为你的技术不错。但可以稍微简化一下:
options.delete(:flight) && options.values.none?
那么:
options.all? {|k,v| k == :fight ? v : !v}
对于更一般的方法:
def is_action?(options, action)
options.all? {|k,v| k == action ? v : !v}
end
is_action? options, :fight
# => true
这一个独立于散列中键/元素的数量
options[:fight] && options.find_all{|arr| !arr[1]}.size == options.size-1
还有一个提示,在ruby中,您永远不需要编写以下内容:
options[:fight] == true
灵感来自Vitaliy的回答:
options[:flight] && options.values.one?
如果您控制散列的内容,并且散列相对较小,我会在私有方法中使用类似的内容作为通用解决方案
def exclusively_true?(hash, key)
return false unless hash.delete(key) == true
!hash.has_value? true
end
require 'test/unit'
class TestExclusive < Test::Unit::TestCase
def setup
@test_hash = {foo: true, bar: false, hoge: false}
end
def test_exclusive
assert_equal(true, exclusively_true?(@test_hash, :foo))
end
def test_inexclusive
@test_hash[:bar] = true
assert_equal(false, exclusively_true?(@test_hash, :foo))
end
end
require 'benchmark'
h = {foo: true}
999.times {|i| h["a#{i}"] = false}
Benchmark.bmbm(30) do |x|
x.report('exclusively_true') do
1000.times do
exclusively_true?(h, :foo)
end
end
end
不完全比他们已经使用的黑客“更优雅”,伊姆霍。哦,我最喜欢count(true)一个,尽管这一个很有趣。同样的事情,但是(5个字符;)更短:
options.select{u124;,v | v}.keys=[:fight]
@tessi,这不是一回事。Priti显式地检查true
而不是真实性。这篇文章可能不会“假”为真。哈!你说得对。在给出的示例中,我假设所有值都是布尔值。但是,如果:flight
不是nil
或false
,它也会返回true。此外,它会破坏选项哈希(尽管在本例中可能并不重要),就像它不会破坏哈希一样。有时,它只会有助于从逻辑上思考您试图完成的任务。优秀的方法+1。是的,我知道怎么做,但是有一个通用的解决方案吗?可能会有更多的选项传入,我只想在fight:为true,其余为false时返回true。我想不出比@Shawn Balestracci的答案更简洁的答案了。据我所知,它们不应该被忽略,但它们都应该是false
你可以用“hash.delete(key)”将其缩短==true&&!hash.has_value?(true)“但是预先建立拒绝案例将有助于未来的开发人员阅读您的代码。可读性和优化远比聪明的一行程序重要。
options[:flight] && options.values.one?
options.select{ |k, v| v } == [[:fight, true]]
def exclusively_true?(hash, key)
return false unless hash.delete(key) == true
!hash.has_value? true
end
require 'test/unit'
class TestExclusive < Test::Unit::TestCase
def setup
@test_hash = {foo: true, bar: false, hoge: false}
end
def test_exclusive
assert_equal(true, exclusively_true?(@test_hash, :foo))
end
def test_inexclusive
@test_hash[:bar] = true
assert_equal(false, exclusively_true?(@test_hash, :foo))
end
end
require 'benchmark'
h = {foo: true}
999.times {|i| h["a#{i}"] = false}
Benchmark.bmbm(30) do |x|
x.report('exclusively_true') do
1000.times do
exclusively_true?(h, :foo)
end
end
end
ruby -v: ruby 2.0.0p0 (2013-02-24 revision 39474) [x86_64-darwin12.3.0]
Rehearsal ------------------------------------------------------------------
exclusively_true 0.000000 0.000000 0.000000 ( 0.000412)
--------------------------------------------------------- total: 0.000000sec
user system total real
exclusively_true 0.000000 0.000000 0.000000 ( 0.000331)