2010-06-30 21 views
5

Tôi có yêu cầu trong dự án .net nơi tôi cần chọn một mục từ bộ sưu tập, mỗi mục có một Trọng số (số nguyên từ 1 đến 10) được gán cho nó. Tôi cần một máy phát ngẫu nhiên sẽ cân nhắc trọng lượng này, tức là, trọng lượng càng cao thì cơ hội càng được chọn càng nhiều. Bất kỳ mẫu mã trong .net được đánh giá cao, mặc dù mô tả thuật toán là tốt đẹp, quá.Tôi cần thuật toán ngẫu nhiên với các tùy chọn cân trong .net

Chỉnh sửa: Sao chép nhanh/dán mã C# trong trường hợp ai đó tình cờ gặp phải điều này.

class RandomWeightedSelector<T> 
    { 
     private List<T> items = new List<T>(); 

     public void Add(T item, uint weight = 1) 
     { 
      for (int i = 0; i < weight; i++) 
       items.Add(item); 
     } 

     public T GetRandom() 
     { 
      return items[new Random().Next(0, items.Count)]; 
     } 
    } 
+1

Bạn không muốn phải tạo ra một ngẫu nhiên mới mỗi cuộc gọi cho 'GetRandom'. Hàm khởi tạo mặc định cho 'Random' hạt giống máy phát có thời gian hoạt động của hệ thống tính bằng mili giây. Nếu bạn gọi 'GetRandom' của bạn nhiều hơn một lần một phần nghìn giây, bạn sẽ được trả về cùng một giá trị. Thậm chí nếu bạn không, bạn có thể trả về kết quả có 'ngẫu nhiên' tồi tệ hơn là chỉ tái sử dụng một cá thể 'Random' duy nhất. – Dolphin

Trả lời

8

Đây là thuật toán không yêu cầu thêm các mục nhiều lần vào danh sách. Nó cũng có thể làm việc với trọng số không nguyên, mặc dù nếu bạn đang sử dụng NextDouble từ System.Random, bạn sẽ phải mở rộng tất cả các trọng số để thêm tối đa 1 hoặc nhân giá trị từ NextDouble với S để lấy nó phạm vi mong muốn.

Cho một danh sách L các hạng mục (I, W), nơi tôi là mục và W là trọng lượng:

  1. Thêm tất cả các trọng lượng với nhau. Gọi số tiền này S.
  2. Tạo một số ngẫu nhiên từ 0 đến S (trừ S, nhưng bao gồm 0). Gọi giá trị này R.
  3. Khởi tạo biến thành 0 để theo dõi tổng số đang chạy. Chúng tôi sẽ gọi T.
  4. này Đối với mỗi mục (I, W) trong L:
    1. T = T + W
    2. Nếu T> R, trở I.
+0

Thay vì mở rộng trọng số của bạn, bạn chỉ có thể sử dụng 'NextDouble() * S' –

+0

@Justin: Vâng, điều đó cũng sẽ hoạt động. Tôi đã cập nhật bài đăng của mình cho phù hợp. –

4

Tạo danh sách và chèn từng mục vào Số lần trọng lượng. Sau đó chọn một mục ngẫu nhiên từ danh sách.

+0

Cảm ơn, điều đó thật đơn giản :) –

+1

Cần lưu ý rằng điều này có tác dụng vì trọng lượng của bạn luôn là số nguyên. –

+0

Vâng, đó là một yêu cầu. Trọng lượng sẽ luôn là số nguyên và ít nhất 1. Giới hạn trọng lượng trên không quan trọng. –

1

Những gì bạn đang tìm kiếm được gọi là thuật toán Chọn trọng số. Tôi thực sự đã tạo một dự án C# nguồn mở cho thời gian này trước đây!

Rất dễ sử dụng và hiệu quả. Ngoài ra, tài liệu sẽ giúp bạn không gặp vấn đề gì.

Dưới đây là một số liên kết:

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