2016-02-26 18 views

Trả lời

2

Đây là điều mà tôi nghĩ rằng vẻ bề ngoài nhiều hơn hoặc ít tốt đẹp, nhưng không phải là hiệu quả vì nó có thể là:

yourCollection asSet asOrderedCollection shuffled first: numberOfElements 
+0

Rất thanh lịch. Cách duy nhất tôi có thể thấy để cải thiện hiệu quả (thường không phải là vấn đề, nhưng một số người bị treo trên đó ...) sẽ khuấy động _indices_ thay vì thu thập (vì sẽ có ít chỉ mục hơn) , và sau đó sử dụng một cái gì đó như '#atAll:' để chọn các chỉ mục ngẫu nhiên trong một tập hợp (bạn vẫn cần '# asSet' nếu bạn muốn chúng _distinct_). –

5

Hãy xem xét đoạn mã sau

sample: anInteger from: aCollection using: aGenerator 
    | sample | 
    sample := Set new: anInteger. 
    [sample size = anInteger] 
    whileFalse: [ | element | 
     element := aCollection atRandom: aGenerator. 
     sample add: element]. 
    ^sample asArray 

Một số nhận xét

  • Máy phát điện rõ ràng: Sử dụng một trình tạo được cho một cách rõ ràng, ví dụ: một phiên bản của Random, mà tôi đã gọi là aGenerator. Vì lý do toán học, nếu bạn đang lấy mẫu cho ứng dụng của mình, tất cả chúng nên sử dụng cùng một trình tạo trên chương trình của bạn. Ngoài ra điều này sẽ cung cấp cho bạn một lợi thế bổ sung: lưu và sau đó khôi phục lại seed và bạn sẽ có thể tái tạo một hành vi "ngẫu nhiên" trước đó của hệ thống của bạn, đó là tốt cho thử nghiệm.

  • Không séc trị giá tính sẵn sàng: Các mã không kiểm tra xem nó có thể để có được những mẫu mong muốn, đó sẽ là trường hợp nếu aCollection không có ít nhất anInteger yếu tố khác nhau.

  • Mã không lớp: Phương pháp nên chuyển đến một số lớp học.

Ví dụ:

Random >> sample: anInteger from: aCollection 
    | sample | 
    sample := Set new: anInteger. 
    [sample size = anInteger] 
    whileFalse: [ | element | 
     element := aCollection atRandom: self. 
     sample add: element]. 
    ^sample asArray 

CẬP NHẬT

Đây là cách tiếp cận khác:

Random >> remove: anInteger from: aCollection 
    | sample | 
    sample := OrderedCollection new: anInteger. 
    anInteger timesRepeat: [| index element | 
    index := aCollection size atRandom: self. 
    element := aCollection removeAt: index. 
    sample add: element]. 
    ^sample 

Comment

Thường xảy ra khi chúng tôi muốn lấy mẫu mà không lặp lại, chúng tôi cũng muốn xóa các phần tử khỏi bộ sưu tập khi chúng tôi chọn ngẫu nhiên chúng. Trong những trường hợp này, điều thường xảy ra là bộ sưu tập được biết là không có sự lặp lại.

+1

Hmm, tôi thích phương pháp "máy phát điện byo", nhưng nếu bộ sưu tập và kích thước mẫu lớn, bạn có thể bị kẹt về phía cuối chờ đợi một thời gian cho đến khi máy phát điện cuối cùng chọn một số "miễn phí". –

+0

@ AmosM.Carpenter điểm tốt. Những gì tôi sử dụng là gần gũi hơn với cách tiếp cận thứ hai. –

+1

Xin lỗi để được nitpicky, nhưng bạn không nên sử dụng '#removeIndex:' - nó có nghĩa là để được tư nhân. Sử dụng phương thức public '#removeAt:' thay vào đó sẽ có lợi ích bổ sung khi trả lời phần tử đã loại bỏ, có nghĩa là bạn có thể loại bỏ biến tạm thời 'element' bổ sung (tức là chỉ cần' sample add: (aCollection removeAt: index) ') .Cả hai phương thức "remove" đều nằm trong 'OrderedCollection', vì vậy nó sẽ không hoạt động với các loại collection khác. –

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