2010-10-18 24 views
10

Hãy nói rằng tôi có các mảng sau:Cung cấp một proc đến một phương pháp như là một khối

arr = [[5, 1], [2, 7]] 

và tôi muốn tìm các phần tử tối thiểu, so sánh phần tử thứ hai trong những yếu tố. Phần tử tối thiểu sẽ là [5, 1] từ 1 nhỏ hơn 7. Tôi có thể sử dụng đoạn mã sau:

arr.min {|a,b| a[1] <=> b[1]} 

Để tính toán mức tối đa, tôi có thể làm điều tương tự:

arr.max {|a,b| a[1] <=> b[1]} 

Điều đó cho [2, 7].

Tôi luôn sử dụng cùng một khối. Tôi muốn có khối đó ở đâu đó và cung cấp nó cho hàm min/max. Tôi hy vọng một cái gì đó như:

blo = lambda {|a,b| a[1] <=> b[1]} 
arr.min blo 

sẽ hoạt động, nhưng không. Bất kỳ ý tưởng về cách tôi có thể làm điều này?

Trả lời

23

Sử dụng toán tử & để biến đối tượng Proc thành một khối.

arr.min &blo 
+2

Người duy nhất đọc câu hỏi cẩn thận. – Nakilon

+0

Đây chính xác là những gì tôi đang tìm kiếm. Cám ơn đã trả lời! –

+0

@Cristobal có lẽ bạn nên "chấp nhận" câu trả lời bạn hài lòng. Nó chỉ ra cho người dùng khác rằng câu hỏi này đã được trả lời và câu trả lời được chấp nhận. –

2

thế nào về điều này?

=> [[5, 4], [9, 5], [2, 7]] 
>> arr.sort!{|x,y| x[1]<=>y[1] } 
=> [[5, 4], [9, 5], [2, 7]] 
>> min,max=arr[0],arr[-1] 
=> [[5, 4], [2, 7]] 
13

@ câu trả lời sepp2k là một trong những tổng quát hơn, nhưng trong trường hợp cụ thể của bạn, tôi sẽ chỉ cần sử dụng

arr.min_by(&:last) 
arr.max_by(&:last) 

vì đó là nhiều rõ ràng hơn tất cả những dấu ngoặc nhọn và dấu ngoặc vuông và chỉ số mảng nổi xung quanh.

+0

Điều này cũng hoạt động;) –

+0

Đó là những gì tôi đang tìm kiếm, vì vậy bạn có thể làm 'line_items.max_by (&: quantity)' chẳng hạn. Cảm ơn rất nhiều – Dorian

1

Một giải pháp tổng quát hơn cho các vấn đề như thế này là tránh hoàn toàn các mảng lồng nhau và sử dụng một lớp thay thế. Sau đó bạn có thể xác định toán tử < => cho lớp đó, cho phép bạn truy cập vào tất cả các hàm trong mixin có thể so sánh (http://ruby-doc.org/core/classes/Comparable.html) cung cấp cho bạn <, < = , ==,> = và> toán tử và phương thức 'giữa?'

Đây chỉ là một ví dụ, trong cuộc sống thực bạn sẽ sử dụng các lớp mô tả những gì họ lưu trữ:

class Duo 

    include Comparable 

    def initialize(a, b) 
     @a = a 
     @b = b 
    end 

    def <=>(rhs) 
     @b <=> rhs.b 
    end 

end 

Nếu bạn có một mảng của Duo đối tượng sau đó bạn có thể sử dụng min, max, và sắp xếp các chức năng mà không cần phải xác định toán tử so sánh. Vì vậy, ...

@a = Duo.new(1, 10) 
@b = Duo.new(2, 5) 
@c = Duo.new(3, 1) 

[ @a, @b, @c ].sort 

sẽ trả lại mảng [@c, @b, @a]

[@a, @b, @c].max 

sẽ trở @a

Đây là nhiều hơn ' Ruby Way 'hơn so với cấu trúc dữ liệu lồng nhau với logic dựa vào vị trí trong mảng. Phải mất nhiều công việc hơn một chút khi bắt đầu, nhưng bạn sẽ tìm thấy nó nhiều hơn tốt hơn về lâu dài.

Ruby là một ngôn ngữ lập trình hướng đối tượng rất và cung cấp các công cụ rất mạnh mẽ để bạn sử dụng. Tôi khuyên bạn nên đọc một cuốn sách như "Ngôn ngữ lập trình Ruby" hoặc "Con đường Ruby" để có được cái nhìn tổng quan về sức mạnh của ngôn ngữ.

+0

Tên 'Duo' không cho biết nó sắp xếp theo phần tử cuối cùng. Điều gì xảy ra nếu ai đó tạo ra một 'Duo' được sắp xếp bởi phần tử đầu tiên cho một phần của dự án, dẫn đến hai' Duo' khác nhau? –

+0

Điều đó luôn luôn là một vấn đề trong bất kỳ mã nào bạn viết, nếu bạn tạo một lớp và một người khác cũng sửa đổi nó thì bạn có một vấn đề. Nhưng đó không phải là lý do để không làm điều đó. Tất nhiên đây chỉ là một ví dụ. Trong cuộc sống thực, bạn sẽ có một tên lớp mô tả hơn nhiều mà thực sự mô tả những gì đã được lưu trữ, không chỉ là một cửa hàng hai mục chung chung. –

+0

Xin chào, cảm ơn bạn rất nhiều vì đã trả lời. Tôi thích nó rất nhiều và tôi đồng ý với bạn, về lâu dài thì tốt hơn. Tuy nhiên, trong dịp này, tôi nhanh chóng vượt qua khối. –

3

Nếu tất cả những gì bạn cần là tối thiểu và tối đa, bạn có thể sử dụng Enumerable#minmax phương pháp và tính toán cả hai cùng một lúc:

min, max = arr.minmax {|a,b| a[1] <=> b[1]} 
#=> [[5, 1], [2, 7]] 
min 
#=> [5, 1] 
max 
#=> [2, 7] 

Edit: Địa ngục, tôi chỉ nhận thấy vẫn còn có minmax_by, vì vậy bạn có thể kết hợp nó với Phương pháp last và có:

min, max = arr.minmax_by &:last 
Các vấn đề liên quan