如果散列中只有一个特定键具有真值,则返回true(所有其他值均为false)

时间:2013-05-22 18:53:48

标签: ruby hash

例如:

options = { fight: true,
 use_item: false,
 run_away: false,
 save_game: false }

我想要一个布尔表达式,其评估结果为true iff仅:fighttrue,其余为false(如上图所示)。

我可以一起破解这个,但我正在努力训练自己写出更优雅的红宝石。谢谢!

编辑:黑客正在:

(options[:fight] == true && options.delete(:fight).values.all {|x| !x})

8 个答案:

答案 0 :(得分:9)

假设所有值都是严格的布尔值,它就像:

一样简单
options == {fight: true, use_item: false, run_away: false, save_game: false}

See documentation for the == method

答案 1 :(得分:8)

受Vitaliy的回答启发:

options[:flight] && options.values.one?

答案 2 :(得分:2)

我认为你的黑客并不坏。它可以简化一点:

options.delete(:flight) && options.values.none?

答案 3 :(得分:1)

options.find_all{|k,v| v } == [[:fight, true]]

options.values.count(true) == 1 && options[:fight]

答案 4 :(得分:1)

怎么样:

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

答案 5 :(得分:1)

这个与散列中的键/元素数无关。

options[:fight] && options.find_all{|arr| !arr[1]}.size == options.size-1

同样只是一个提示,在红宝石中,你永远不需要写下这样的东西:

options[:fight] == true

答案 6 :(得分:0)

options.select{ |k, v| v } == [[:fight, true]]

答案 7 :(得分:0)

如果您控制散列的内容,并且它相对较小,我会在私有方法中使用类似的东西作为通用解决方案。

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

受控基准:(OS X 10.8.3 / 3 GHz / 8 GB)

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)