2013-05-22 18 views
5

Ví dụ:Làm thế nào để trở về đúng nếu chỉ có một chìa khóa cụ thể trong một hash có giá trị đúng (tất cả các giá trị khác là sai)

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

Tôi muốn có một biểu thức boolean mà đánh giá để true iff chỉ :fighttrue và phần còn lại là false (như minh họa ở trên).

Tôi có thể cùng nhau hack, nhưng tôi đang cố gắng rèn luyện bản thân để viết thêm ruby ​​thanh lịch. Cảm ơn!

EDIT: Các hack phúc:

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

Trả lời

8

Lấy cảm hứng từ Vitaliy của câu trả lời:

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

như thế nó không phá hủy băm –

+0

Đôi khi nó chỉ giúp suy nghĩ một cách hợp lý những gì bạn đang cố gắng để thực hiện. Cách tiếp cận tuyệt vời +1. – squiguy

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

hoặc

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

Không chính xác "tao nhã" hơn hack họ đang sử dụng, IMHO. –

+0

ngữ nghĩa giống như OP –

+0

oh Tôi thích số (đúng) là tốt nhất, mặc dù điều này là thú vị. –

9

Giả sử tất cả các giá trị là đúng boolean, nó đơn giản như:

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

See documentation for the == method

+0

Yup Tôi biết làm thế nào để làm điều đó, nhưng có một giải pháp chung? Có thể có nhiều tùy chọn hơn được chuyển vào, và tôi muốn trả về true nếu chiến đấu: là đúng và phần còn lại là sai. –

+1

Tôi không thể tìm ra bất kỳ điều gì tốt hơn câu trả lời của @Shawn Balestracci cho điều đó. – DanSingerman

+0

Theo như tôi hiểu, họ không nên bỏ qua, nhưng tất cả họ nên là 'false' – tessi

2

Tôi nghĩ rằng hack của bạn không phải là xấu. Nó có thể được đơn giản hóa một chút mặc dù:

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

+1 Đối với sự sang trọng. Tuy nhiên, nó cũng sẽ trả về true nếu ': flight' là _anything_ khác với' nil' hoặc 'false'. –

+0

Cộng với nó phá hủy các tùy chọn băm (mặc dù nó có thể không quan trọng trong trường hợp này) – tessi

1

Làm thế nào về:

options.all? {|k,v| k == :fight ? v : !v} 

Đối với một cách tiếp cận tổng quát hơn:

def is_action?(options, action) 
    options.all? {|k,v| k == action ? v : !v} 
end 

is_action? options, :fight 
# => true 
1

Cái này không phụ thuộc vào số lượng chủ chốt/elems trong băm.

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

Cũng Chỉ cần một mẹo, trong ruby, bạn không bao giờ cần phải viết một cái gì đó như:

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

Nếu bạn kiểm soát nội dung của băm, và nó là tương đối nhỏ, tôi sẽ sử dụng một cái gì đó như thế này trong một phương pháp riêng như một giải pháp chung chung.

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 

chuẩn giả tạo: (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) 
+0

bạn có thể làm ngắn hơn bằng "hash.delete (key) == true &&! Hash.has_value? (True)" nhưng việc thiết lập trường hợp từ chối phía trước sẽ giúp các nhà phát triển tương lai đọc mã của bạn. Khả năng đọc và tối ưu hóa quan trọng hơn nhiều so với một lớp lót thông minh. – randym

Các vấn đề liên quan