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)