2010-03-01 33 views
7

Giả sử tôi có một mảng giá trị [a, b, c, d, ...] và hàm f (x, ...) trả về giá trị true hoặc false.Cách tiếp cận chức năng tốt nhất với AND trên danh sách

[1,2,3,4].map {|x| f(x)} => [true true false true] 

Trước tiên, cách tốt nhất để thu gọn danh sách kết quả thành giá trị đúng hoặc sai (qua AND) là gì? Có một chức năng mà sẽ cho phép tôi để lập bản đồ:

[true true false true] 

tới:

((true && true) && false) && true 

sử dụng một ứng dụng cặp-khôn ngoan tích lũy của các nhị phân điều hành & &?

Trong trường hợp này, chi phí đánh giá chức năng là không hợp lý, vì vậy muốn sử dụng kiểu "và" để đánh giá các đối số (các ứng dụng chức năng) tuần tự cho đến khi một trong số đó sai. Xác định rằng có thể làm:

!![1,2,3,4].each {|x| break false if !f(x) } 

Điều gì là xấu xí. Hy vọng rằng có một cách thanh lịch hơn để làm điều này. Tôi biết rằng tôi có thể thêm một hiểu mới vào mảng, nhưng hy vọng rằng có một cái gì đó được xây dựng trong đó làm điều này tốt hơn. Cảm ơn

Trả lời

12

Bạn đang tìm kiếm Enumerable#all?, trả về true nếu tất cả các lời gọi của khối của nó là trung thực. cũng Enumerable#any? có, mà trả về true nếu bất kỳ lời gọi của khối của nó là truthy:

#!/usr/bin/ruby1.8 

def even(n) 
    n % 2 == 0 
end 

p [1, 2, 3, 4].all? { |i| even(i) } # => false 
p [2, 4, 6, 8].all? { |i| even(i) } # => true 
p [1, 2, 3, 4].any? { |i| even(i) } # => true 
p [1, 3, 5, 7].any? { |i| even(i) } # => false 

any? ngắn curcuits: giá trị truthy đầu tiên làm cho nó trở thành sự thật. Vì vậy, all? ngắn mạch: giá trị falsy đầu tiên làm cho nó trở về sai.

+0

Xin lỗi vì đã viết nitpicking, nhưng 'Fixnum' đã có phương thức' even? 'Và' odd? '...;) –

+0

@Mladen Jablanovic, Good point. Đối với ví dụ này, tôi muốn có một hàm do người dùng định nghĩa. –

1

Làm thế nào về: [true, true, false, true].all?

này sẽ trả về true nếu mảng không chứa bất cứ điều gì mà đánh giá sai hoặc nil.

3

Bạn có thể thử gấp mảng của bạn:

[true,true,false,true].inject(:&) #=> false (AND-ed) 
[true,true,false,true].inject(:|) #=> true (OR-ed) 
[1,2,3,4].inject(:+)    #=> 10 (summed) 
[1,2,3,4].inject(:*)    #=> 24 (multiplied) 

Bạn nhận được các đầu mối. Quay lại ví dụ của bạn:

[1,2,3,4].map {|x| f(x) }.inject(:&) 

Tuy nhiên, nó sẽ không shortcircuit - bạn có thể xem xét tốt hơn "bất kỳ?" hoặc "tất cả?" ngoại trừ "f()" của bạn có các tác dụng phụ (như sửa đổi bộ nhớ liên tục).

+0

Cảm ơn, câu trả lời này là câu hỏi đầu tiên! Wayne trả lời câu hỏi thứ hai. –

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