2009-10-07 42 views
23

Vì vậy, tôi có một lỗi để loại bỏXElements Loại bỏ trong một vòng lặp foreach

foreach (XElement x in items.Elements("x")) 
{ 
    XElement result = webservice.method(x); 

    if (/*condition based on values in result*/) 
    { 
     x.Remove(); 
    } 
} 

Vấn đề là gọi x.Remove() làm thay đổi foreach như vậy mà nếu có hai yếu tố ("x"), và cái đầu tiên bị loại bỏ, vòng lặp không đến được phần tử x thứ hai.

Vậy làm cách nào để tôi lặp lại điều này? Hay điều này nên được viết lại theo cách khác?

+8

Tôi thực sự vừa sửa đổi foreach là "foreach (XElement x trong items.Elements (" x "). Đảo ngược())" và điều đó dường như làm việc tốt như các vấn đề trước khi là foreach chuyển lập chỉ mục và Xóa đã chuyển mọi thứ xuống, khiến các mục bị bỏ qua. Đảo ngược thứ tự có vẻ hợp lý. Nhưng, tôi sẽ để câu hỏi mở ra trong trường hợp ai đó có một giải pháp tốt hơn. – CaffGeek

+0

Tôi đã làm một vòng lặp cho nơi mà tôi đã phải làm một i-- nếu nó thực sự loại bỏ một mục để bù đắp cho chỉ mục. Cách của bạn với đảo ngược dường như không phải là một lựa chọn tồi, mặc dù, nhưng tôi không phải là một chuyên gia .NET, vì vậy tôi là một chút hoài nghi về những gì tôi nói, lol. – Xaisoft

+0

được quay lại C# 3.0. Không có C# với phiên bản 3.5 (xem bài đăng này để biết chi tiết http://stackoverflow.com/questions/247621/what-are-the-correct-version-numbers-for-c) – Vaccano

Trả lời

30

Tôi nghi ngờ rằng LINQ có thể giúp bạn ở đây như sau.

using System.Linq; 

void foo() 
{ 
    items.Elements("x") 
     .Where(x => condition(webservice.method(x))) 
     .Remove(); 
} 

Nếu điều đó không hiệu quả (tức là điều tra viên nội bộ vẫn bị vô hiệu), tạo bản sao nông của các phần tử đã chọn và xóa chúng như sau.

using System.Linq; 

void foo() 
{ 
    List xElements = items.Elements("x") 
          .Where(x => condition(webservice.method(x))) 
          .ToList(); 

    for (int i = xElements.Count - 1; i > -1; i--) 
    { 
     xElements[i].Remove(); 
    } 
} 
+0

+1 Tình huống lý tưởng nếu bạn đang sử dụng .Net 3.5 –

+0

Đoạn mã đầu tiên làm việc cho tôi. Giải pháp tuyệt vời. +1 –

+0

Lưu ý rằng mỗi Remove() đi vào danh sách liên kết nội bộ của các phần tử con từ đứa trẻ đầu tiên trở đi, do đó độ phức tạp tính toán của mỗi loại bỏ là O (N). Có cách nào để loại bỏ các yếu tố O (1) không? – redcalx

1

Tạo bộ sưu tập trước lôgic vòng lặp, thêm các phần tử cần xóa vào bộ sưu tập mới, sau đó gọi các mục. Xóa trên từng phần tử trong bộ sưu tập mới.

+0

Điều này sẽ hoạt động. Tôi nhớ làm điều này. Câu trả lời của tôi có lẽ không tốt. Tôi nhớ điều gì đó về nếu bạn thay đổi một danh sách hoặc một cái gì đó, nó là một ý tưởng tốt để sử dụng cho, nhưng nếu bạn chỉ là looping mà không thực hiện bất kỳ thay đổi, foreach là tốt. Điều này có đúng không? – Xaisoft

1

Hãy thử nó mà không cần thay vì foreach.

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