2013-03-01 35 views
8

Trong C# Tôi đang cố gắng lấy một mục từ danh sách ở chỉ mục ngẫu nhiên. Khi nó đã được lấy ra tôi muốn nó được gỡ bỏ để nó không thể được chọn nữa. Có vẻ như tôi cần rất nhiều hoạt động để làm điều này, không phải là có một chức năng mà tôi có thể chỉ cần trích xuất một mục từ danh sách? Hàm RemoveAt (chỉ mục) bị vô hiệu. Tôi muốn có một giá trị trả lại.Xóa mục khỏi Danh sách và nhận mục đồng thời

Những gì tôi đang làm:

List<int> numLst = new List<int>(); 
numLst.Add(1); 
numLst.Add(2); 

do 
{ 
    int index = rand.Next(numLst.Count); 
    int extracted = numLst[index]; 
    // do something with extracted value... 
    numLst.removeAt(index); 
} 
while(numLst.Count > 0); 

Những gì tôi muốn làm:

List<int> numLst = new List<int>(); 
numLst.Add(1); 
numLst.Add(2); 

do 
{ 
    int extracted = numLst.removeAndGetItem(rand.Next(numLst.Count)); 
    // do something with this value... 
} 
while(numLst.Count > 0); 

Có một "removeAndGetItem" chức năng như vậy tồn tại?

+0

Bạn sẽ phải viết của riêng bạn - theo như tôi biết, chỉ có một Stack hoặc một Hàng đợi có loại chức năng này được tích hợp sẵn. Điều này có cần phải được an toàn không? –

+1

Tại sao không nhận được những gì bạn muốn có một biến/danh sách mới? – Kaf

Trả lời

15

Không, vì nó vi phạm nghi thức hàm thuần túy, trong đó phương thức có tác dụng phụ hoặc trả về giá trị hữu ích (tức là không chỉ báo trạng thái lỗi) - không bao giờ cả hai.

Nếu bạn muốn chức năng xuất hiện nguyên tử, bạn có thể nhận được một khóa trên danh sách, mà sẽ ngừng đề khác truy cập vào danh sách trong khi bạn đang sửa đổi nó:

public static class Extensions 
{ 
    public static T RemoveAndGet<T>(this IList<T> list, int index) 
    { 
     lock(list) 
     { 
      T value = list[index]; 
      list.RemoveAt(index); 
      return value; 
     } 
    } 
} 
+0

Hãy nhớ rằng khóa sẽ chỉ trợ giúp nếu RemoveAndGet được gọi đồng thời. Một số chức năng khác vẫn có thể sửa đổi danh sách, và bạn vẫn sẽ có OutOfBoundsException. Như đã đề cập dưới đây, việc xử lý ngoại lệ có thể được xem xét. – mateuscb

+2

phần đầu tiên về lệnh và truy vấn là không đúng, 'Add' có tác dụng phụ và trả về một giá trị trên cùng một lớp ở đây ... nó cũng không phải lúc nào cũng thực tế, lấy Stack ví dụ,' Pop' có tác dụng phụ và trả về một giá trị. điều đó thật kỳ lạ khi giữ cho hai người đó tách biệt nhau. (Tôi thích ý tưởng về các lệnh và truy vấn, nhưng khái niệm đó không được thực thi trong .NET và không phải lúc nào bạn muốn) –

+0

Cá nhân tôi nghĩ phần "hữu ích" của tôi câu trả lời vẫn áp dụng cho giá trị trả về từ 'Thêm', trong phần lớn các trường hợp sử dụng. – RoadieRich

5
public static class ListExtensions 
{ 
    public static T RemoveAndGetItem<T>(this IList<T> list, int iIndexToRemove} 
    { 
    var item = list[iIndexToRemove]; 
    list.RemoveAt(iIndexToRemove); 
    return item; 
    } 
} 

Đây được gọi là extension methods, gọi là new List<T>().RemoveAndGetItem(0).

Những điều cần xem xét trong phương pháp khuyến nông

ngoại lệ xử lý với chỉ số mà bạn vượt qua, kiểm tra xem các chỉ số được withing 0 và đếm danh sách trước khi làm điều này.

+0

+1 Tôi đoán đây giống như câu trả lời khác với khóa. Cảm ơn bạn đã lưu ý xử lý ngoại lệ. – Eirik

+0

@Eirik Không có đặc điểm kỹ thuật liên quan đến những gì sẽ xảy ra nếu bạn chuyển một chỉ mục không hợp lệ đến một phương pháp trên IList, vì vậy tôi nghĩ tốt hơn là để xác thực đối số để thực hiện danh sách. Đối với tất cả những gì bạn biết, triển khai IList tùy chỉnh có thể là ** mong đợi ** trong số các chỉ mục phạm vi vì bất kỳ lý do gì. – RoadieRich

+0

@RichardLovely đây là lý do chính xác tại sao tôi nói đó là 'điều cần xem xét'. Ngoài ra, những gì possiblity có thể một danh sách tùy chỉnh được mong đợi một chỉ số đó là ngoài phạm vi, ra khỏi tò mò? – LukeHennerley

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