2015-11-13 6 views
1

Вот сценарий, который воспроизводится для каждого цикла, который я делаю;Итерация через IList <>

В принципе, я хочу удалить запись из lstMaster, если есть совпадение в lstChild, но результаты, которые я получаю, не завершены - я должен удалить 800 записей или около того, но я удаляю только 256 записей.

Внешний контур lstMaster имеет 1600 записей. Внутренний цикл: lstChild имеет 800, которые не могут существовать в lstMaster.

Итак, если совпадение встречается в lstChild, запись удаляется в lstMaster.

Я что-то пропущу в петле?

for(int i=lstMaster.Count-1; i > 0; i--) 
    { 
    for(int j=lstChildcare.Count-1; j > 0; j--) 
     { 
     if(lstChildcare[j].school_license == lstMaster[i].school_license) 
     { 
      textboxStatus.AppendText(Text = "Removing duplicate row: " + i     + " School: " + lstMaster[i].school_name + Environment.NewLine); 
        lstMaster.RemoveAt(i); 
        counter++; 

       } 

      } 

     } 
+0

Я предполагаю, что это C#? –

+0

Не могли бы вы определить, какие записи следует удалить, но нет? –

+0

Привет - да, это в C#. Да. Я мог бы идентифицировать записи, которые должны быть перемещены, и они не выводятся. – dawriter

ответ

1

Поскольку вы зацикливание в обратном направлении (начиная с последнего пункта, и заканчивающийся в первом пункте), то вы должны быть в порядке.

Единственная проблема, которую я вижу, - это удалить элемент из lstMaster, а затем попытаться получить доступ к тому же индексу снова в следующем цикле через lstChildcare.

Чтобы исправить это, просто сломайте внутренний цикл, как только вы решите удалить элемент из списка lstMaster. Поскольку вы удалили элемент, нет необходимости продолжать цикл.

Reaplce это:

lstMaster.RemoveAt(i); 
counter++; 

Добавить это:

lstMaster.RemoveAt(i); 
counter++; 
break; 

Если по какой-то причине, вы должны обнаружить все матчи между родительскими и дочерними списками, вы можете просто удалить элемент образует родительский список после того, как вы пропустите дочерний список следующим образом:

for (int i = lstMaster.Count - 1; i > 0; i--) 
{ 
    bool delete = false; 

    for (int j = lstChildcare.Count - 1; j > 0; j--) 
    { 
     if (lstChildcare[j].school_license == lstMaster[i].school_license) 
     { 
      textboxStatus.AppendText(MediaTypeNames.Text = "Removing duplicate row: " + i + " School: " + lstMaster[i].school_name + Environment.NewLine); 
      delete = true; 
      counter++; 
     } 
    } 

    if(delete) 
     lstMaster.RemoveAt(i); 
} 
-1

Никогда не удаляйте элементы из списка непосредственно внутри цикла.

Размер списка меняется!

Таким образом, цикл for, который выполняет итерацию по списку, фактически не видит каждый элемент.

Например, если вы удалите элемент 2, то i получает приращение до 3 для следующего элемента. Но старый элемент 3 теперь стал 2. Таким образом, этот элемент никогда не проверяется.

Вместо этого создайте новый список items_to_be_deleted, в то время как в цикле добавьте, какие элементы необходимо удалить.

После этого удалите эти предметы.

+0

Это имеет смысл. После создания списка items_to_be_deleted я создаю еще один цикл? Поскольку я хочу удалить элементы из lstMaster, поэтому я прохожу через lsMaster.RemoveAt (items_to_be_deleted) ...? – dawriter

+0

Вы можете попробовать 'list2.Except (list1) .ToList();'. Еще одна вещь, которую нужно изучить - это метод 'removeAll', который использует предикат. –

+1

Это имеет смысл ... Но OP петли в обратном порядке, так что это действительно не применимо –

2

Если ваши списки на самом деле являются конкретным типом List<T>, то вы можете удалить нежелательные предметы с помощью совпадения Predicate(T) в методе RemoveAll. Вы также можете наследовать объект ChildCare от IEquatable<T>, чтобы контролировать, как он считается равным, и сделать что-то похожее ниже. Я сделал вещи, потому что я не знаю, что в вашем фактическом классе, кроме лицензии, но вы можете получить эту идею из этого примера. Вы можете скопировать и вставить его прямо в LinqPad и запустить его, чтобы попробовать.

void Main() 
{ 
    var masterChildcare = new List<ChildCare> 
    { 
    new ChildCare{SchoolLicense= "One"}, 
    new ChildCare{SchoolLicense= "Two"}, 
    new ChildCare{SchoolLicense= "Three"}, 
    new ChildCare{SchoolLicense= "Four"}, 
    new ChildCare{SchoolLicense= "Five"}, 
    new ChildCare{SchoolLicense= "Six"}, 
    new ChildCare{SchoolLicense= "Seven"}, 
    new ChildCare{SchoolLicense= "Eight"}, 
    new ChildCare{SchoolLicense= "Nine"}, 
    new ChildCare{SchoolLicense= "Ten"}, 
    }; 
    var childChildcare = new List<ChildCare> 
    { 
     new ChildCare{SchoolLicense= "Three"}, 
     new ChildCare{SchoolLicense= "Eight"}, 
     new ChildCare{SchoolLicense= "Nine"} 
    }; 
    masterChildcare.Dump(); 

    masterChildcare.RemoveAll(childCare => childChildcare.Contains(childCare)); 
    masterChildcare.Dump(); 

} 

public class ChildCare : IEquatable<ChildCare> 
{ 
    public string SchoolLicense { get; set;} 

    public bool Equals(ChildCare other) 
    { 
     if (other == null) 
     { 
      return false; 
     } 

     if (SchoolLicense == other.SchoolLicense) 
     { 
      return true; 
     } 
     return false; 
    } 

    public override bool Equals(object obj) 
    { 
     if (obj == null) 
     { 
      return false; 
     } 

     ChildCare other = obj as ChildCare; 
     if (other == null) 
     { 
      return false; 
     } 
     return Equals(other); 
    } 

    public override int GetHashCode() 
    { 
     return SchoolLicense.GetHashCode(); 
    } 
} 

enter image description here

Смежные вопросы