2008-11-14 41 views
5

Tôi có một danh sách các mảng có chứa các mục có tên là Room. Mỗi phòng có một loại phòng như nhà bếp, lễ tân, vv Tôi muốn kiểm tra danh sách để xem nếu có bất kỳ phòng nào thuộc loại đó tồn tại trước khi thêm nó vào danh sách. Bất cứ ai có thể giới thiệu một cách gọn gàng để làm điều này mà không cần nhiều vòng foreach?kiểm tra các mục trùng lặp trong arraylist

(NET 2,0)


tôi havent có quyền truy cập vào các công nghệ LINQ như đang chạy trên .net 2.0. Tôi nên nói rằng trong câu hỏi. Xin lỗi

Trả lời

10

Tôi sẽ không sử dụng ArrayList tại đây; kể từ khi bạn có .NET 2.0, sử dụng List<T> và tất cả trở nên đơn giản:

List<Room> rooms = ... 
string roomType = "lounge"; 
bool exists = rooms.Exists(delegate(Room room) { return room.Type == roomType; }); 

Hoặc với C# 3.0 (vẫn nhắm mục tiêu NET 2,0)

bool exists = rooms.Exists(room => room.Type == roomType); 

Hoặc với C# 3.0 và một trong hai LINQBridge hoặc .NET 3.5 :

bool exists = rooms.Any(room => room.Type == roomType); 

(việc sử dụng Any sẽ làm việc với nhiều loại, không chỉ List<T>)

1
if (!rooms.Any (r => r.RoomType == typeToFind /*kitchen, ...*/)) 
    //add it or whatever 
+0

ah xin lỗi của tôi đang chạy trên .net 2 không may – anonym0use

+0

Với VS2008, điều này sẽ làm việc tốt với .NET 2. –

+0

@OJ: với 2.0, chỉ khi bạn sử dụng LINQBridge ... Bất kỳ được cung cấp bởi .NET 3.5; bạn có thể sử dụng cú pháp Exists với C# 3.0 lambdas, tuy nhiên –

0

Tôi đã nghĩ đến việc sử dụng danh sách và thực hiện Exists khi một hoạt động mất thời gian O(n). Sử dụng Dictionary thay vì là O(1) và được ưu tiên nếu bộ nhớ không phải là vấn đề.

Nếu bạn không cần danh sách tuần tự tôi sẽ cố gắng sử dụng một Dictionary như thế này:

Dictionary<Type, List<Room>> rooms = new Dictionary<Type, List<Room>>; 

void Main(){ 
    KitchenRoom kr = new KitchenRoom(); 
    DummyRoom dr = new DummyRoom(); 
    RoomType1 rt1 = new RoomType1(); 
    ... 

    AddRoom(kr); 
    AddRoom(dr); 
    AddRoom(rt1); 
    ... 

} 

void AddRoom(Room r){ 
    Type roomtype = r.GetType(); 
    if(!rooms.ContainsKey(roomtype){ //If the type is new, then add it with an empty list 
    rooms.Add(roomtype, new List<Room>); 
    } 
    //And of course add the room. 
    rooms[roomtype].Add(r); 
} 

Bạn về cơ bản có một danh sách roomtypes khác nhau. Nhưng giải pháp này chỉ là OK nếu bạn không cần arraylist. Nhưng đối với các danh sách lớn, đây sẽ là danh sách nhanh nhất.

Tôi đã có giải pháp một lần với List<string> với 300.000+ mục. So sánh từng phần tử với một danh sách có kích thước gần như giống nhau đã mất 12 giờ để làm. Đã thay đổi logic để sử dụng từ điển thay vì và giảm xuống còn 12 phút. Đối với các danh sách lớn hơn, tôi luôn luôn đi Dictionary<mytype, bool> trong đó bool chỉ là một giả không được sử dụng.

0

Nếu không sử dụng các biểu thức lambda:

void AddRoom(Room r, IList<Room> rooms, IDictionary<string, bool> roomTypes) 
{ 
    if (!roomTypes.Contains(r.RoomType)) 
    { 
     rooms.Add(r); 
     roomTypes.Add(r.RoomType, true); 
    } 
} 

Nó không thực sự có vấn đề gì loại giá trị trong từ điển là, bởi vì điều duy nhất bạn đã bao giờ nhìn vào là các phím.

0

Cách khác là sắp xếp mảng, sau đó đi bộ các phần tử cho đến khi bạn tìm thấy cặp bản sao liền kề. Làm cho nó đến cùng, và mảng là miễn phí.

1

Từ câu hỏi của bạn, nó không phải là 100% rõ ràng với tôi nếu bạn muốn thực thi quy tắc có thể chỉ có một phòng thuộc một loại nhất định hoặc nếu bạn chỉ muốn biết.

Nếu bạn có bất biến mà không có bộ sưu tập nào của Room s có thể có nhiều loại cùng loại Room, bạn có thể thử sử dụng Dictionary<Type, Room>.

Điều này có lợi khi không thực hiện tìm kiếm tuyến tính khi thêm.

Bạn sẽ thêm một căn phòng bằng cách sử dụng các hoạt động sau:

if(rooms.ContainsKey(room.GetType())) 
{ 
    // Can't add a second room of the same type 
    ... 
} 
else 
{ 
    rooms.Add(room.GetType(), room); 
} 
Các vấn đề liên quan