Як вярнуць ісціну, калі толькі адзін канкрэтны ключ у хэш мае сапраўднае значэнне (усе астатнія значэння з'яўляюцца ілжывымі)

Напрыклад:

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

Я хачу, каб лагічны выраз, якое вылічае True тады і толькі тады толькі : бой гэта True , а астатнія хлусня ( як паказана вышэй).

Я магу ўзламаць гэта разам, але я стараюся трэніраваць сябе, каб напісаць больш элегантны рубін. Дзякуй!

EDIT: Секчы істота:

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

5

8 адказы

Мяркуючы, што ўсё значэнні строга лагічныя, гэта так проста, як:

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

Глядзіце дакументацыю для метаду == </а>

9
дададзена
Я не магу прыдумаць нічога больш succint, чым адказ @Shawn Balestracci для гэтага.
дададзена аўтар DanSingerman, крыніца
Так, я ведаю, як зрабіць гэта, але ёсць агульнае рашэнне? Там можа быць больш варыянтаў прайшлі, і я хачу, каб вярнуцца дакладна, толькі калі бой: праўду, а астатнія з'яўляюцца ілжывымі.
дададзена аўтар Kyra Westwood, крыніца
Наколькі я разумею, яны не павінны быць праігнараваныя, але ўсе яны павінны быць хлусня
дададзена аўтар tessi, крыніца

Натхнёны адказ Віталя:

options[:flight] && options.values.one?
8
дададзена
як, што ён не разбурае хэш
дададзена аўтар Vitaliy Yanchuk, крыніца
Часам ён проста дапамагае лагічна думаць, што вы спрабуеце дасягнуць. Выдатны падыход +1.
дададзена аўтар squiguy, крыніца

Я думаю, што ваш хак не плохо. Гэта можа быць спрошчана трохі, хоць:

options.delete(:flight) && options.values.none?
2
дададзена
Акрамя таго, ён знішчае варыянты хэш (хоць гэта можа быць не важна ў дадзеным выпадку)
дададзена аўтар tessi, крыніца
+1 Для элегантнасці. Тым не менш, ён таксама вяртае ісціну, калі : палёт гэта <�я> што-небудзь </я> акрамя NIL або ілжывым .
дададзена аўтар Charles Caldwell, крыніца
options.find_all{|k,v| v } == [[:fight, true]]

або

options.values.count(true) == 1 && options[:fight]
1
дададзена
@ShawnBalestracci Гэта нармальна?
дададзена аўтар Arup Rakshit, крыніца
семантычна жа, як і OP
дададзена аўтар Rune FS, крыніца
Тое ж самае, але (5 знакаў;)) карацей: options.select {| _, v | v} .keys == [: барацьба]
дададзена аўтар tessi, крыніца
Har! Ты маеш рацыю. З прыведзеных прыкладам, я меркаваў, усе значэння з'яўляюцца лагічнымі.
дададзена аўтар tessi, крыніца
Не зусім «больш хупавы», чым хак яны ўжо выкарыстоўваюць, ІМХО.
дададзена аўтар Charles Caldwell, крыніца
ой я любіў графа (праўда) адзін лепшы, хоць гэта адзін цікавы.
дададзена аўтар Shawn Balestracci, крыніца
@tessi, гэта не тое ж самае. Прытым відавочна праверка True замест truthiness. ОП можа не "хлусьня", каб быць праўдай.
дададзена аўтар Shawn Balestracci, крыніца
Я не люблю _, як вы не ведаеце, што папярэдняя каманда, але так, яны абодва працуюць інакш.
дададзена аўтар Shawn Balestracci, крыніца

Як наконт:

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
1
дададзена

Гэта адзін не залежыць ад колькасці ключавых/elems ў хэш.

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

Акрамя таго, толькі наканечнік, рубіну, вам не трэба пісаць нешта накшталт:

options[:fight] == true
1
дададзена
options.select{ |k, v| v } == [[:fight, true]]
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 Ггц/8 ГБ) </моцны>

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)
0
дададзена
Вы можаце зрабіць гэта карацей з «hash.delete (ключ) == праўдзівы &&! Hash.has_value? (Праўда)», але ўсталяванне адхіляць справы фронту дапаможа будучым распрацоўнікам чытаць ваш код. Чытальнасць і аптымізацыя з'яўляецца значна больш важнай, чым разумныя лайнеры.
дададзена аўтар randym, крыніца