Удалить дубликаты в одном наборе данных относительно другого в C # - PullRequest
0 голосов
/ 25 июня 2018

Я новичок в C #.Попытка удалить дубликаты в CollectionIn1, но это не работает.Дубликаты в CollectionIn не удаляются.

Просто для пояснения, collectionIn имеет [A, B, C, D], а collectionIn2 имеет [A, B, C].

Итак, я хочу удалить значения (A, B, C) в collectionIn

for (int i = 0; i < CollectionIn.Rows.Count; i++) {
    string value1 = CollectionIn.Rows[i].ItemArray[0].ToString().ToLower(); 

    for (int i2 = 0; i2 < CollectionIn2.Rows.Count; i2++) {
        string value2 = CollectionIn2.Rows[i2].ItemArray[0].ToString().ToLower(); 

        if (value1 == value2) {
            //Remove value1 when value1 == value2
            CollectionIn.Rows[i].Delete(); <--- Trying to delete when there is duplicate in both collections

            CollectionIn.AcceptChanges();
        }
    }
    //CollectionOut.Rows.Add(value1);
}

Я сделал некоторые изменения по этой ссылке http://www.rpaforum.net/threads/how-to-compare-two-excel-sheet-using-c-code-in-blueprism.897/

Ответы [ 5 ]

0 голосов
/ 25 июня 2018
mylist2 = mylist2.Distinct().ToList();
mylist1.RemoveAll(item => mylist2.Contains(item));
0 голосов
/ 25 июня 2018

Сравнение двух наборов может иметь сложность O (n2). Это плохо. Вы можете улучшить это, если у вас есть начальный поиск хеша.

var Set1 = new Dictionary<string, int>();

//Prehash all values in the set that won't be deleted from 
for (int i = 0; i < CollectionIn.Rows.Count; i++)
{
    string value1 = CollectionIn.Rows[i].ItemArray[0].ToString().ToLower();
    Set1.Add(value1, i);
}

//Loop over the other set
for (int i2 = 0; i2 < CollectionIn2.Rows.Count; i2++)
{
    string value2 = CollectionIn2.Rows[i2].ItemArray[0].ToString().ToLower();

    int foundIndex;
    if (Set1.TryGetValue(value2, out foundIndex) == false)
        continue;

    //Remove value1 when value1 == value2
    CollectionIn.Rows[foundIndex].Delete();
}
CollectionIn.AcceptChanges(); //It's probably best to save changes last as a single call

I хэшируется CollectionIn, а затем повторяется CollectionIn2. Это означает, что мне нужен словарь, поэтому для удаления мне нужен индекс CollectionIn. Если бы это было наоборот, и CollectionIn2 был хеширован, то это был бы только хэш-набор, и было бы лучше, потому что он мог бы обрабатывать внутренние дубликаты в наборе CollectionIn, поэтому:

var Set2 = new HashSet<string>();

//Prehash all values in one set (ideally the larger set)
for (int i2 = 0; i2 < CollectionIn2.Rows.Count; i2++)
{
    string value2 = CollectionIn2.Rows[i2].ItemArray[0].ToString().ToLower();

    if (Set2.Contains(value2))
        continue; //Duplicate value
    else
        Set2.Add(value2);
}

//Loop over the other set
for (int i1 = 0; i1 < CollectionIn.Rows.Count; i1++)
{
    string value1 = CollectionIn.Rows[i1].ItemArray[0].ToString().ToLower();

    if (Set2.Contains(value1) == false)
        continue;

    //Remove value1 when value1 == value2
    CollectionIn.Rows[i1].Delete();
}

CollectionIn.AcceptChanges(); //It's probably best to save changes last as a single call

Этот шаблон будет применяться ко многим типам наборов данных (включая Список, массив и т. Д.). Конечно, если вы можете написать SQL для удаленных наборов данных в той же базе данных, это лучше.

Если вы любите лямбда-функции, это должно выглядеть примерно так:

var alreadyInSet2 = new HashSet<string>(CollectionIn2.Rows.Cast<DataRow>()
                    .Select(x => x[0].ToString().ToLower()));

CollectionIn.Rows.Cast<DataRow>()
                    .Where(y => alreadyInSet2.Contains(y[0].ToString().ToLower()) == false)
                    .ToList() //I think you technically need this before calling ForEach
                    .ForEach(y => y.Delete());

CollectionIn.AcceptChanges();                   

См. Также: С двумя очень большими списками / коллекциями - как эффективно обнаруживать и / или удалять дубликаты - где больше времени / работы может уйти в более широкий порядок ответов и повышения производительности.

0 голосов
/ 25 июня 2018
foreach(var row in CollectionIn.Rows.Cast<DataRow>()
    .Where(x => CollectionIn2.Rows.Cast<DataRow>()
    .Any(y => y[0].ToString().ToLower() == x[0].ToString().ToLower())))
{
    row.Delete();
}
CollectionIn.AcceptChanges();

Не самая лучшая производительность, но она работает и легко читается.

Также в вашем коде есть ошибка из-за изменения коллекций во время их итерации.

0 голосов
/ 25 июня 2018

Это работает и легко понять.

List<string> List1 = new List<string> { "A", "B", "C", "D" };
List<string> List2 = new List<string> { "A", "B", "C" };
List<string> ListTemp = new List<string>();

foreach (string str1 in List1)
{
     foreach (string str2 in List2)
     {
          if (str1 == str2)
          {
               ListTemp.Add(str1);
          }
     }
 }            

foreach (string temp in ListTemp)
{
     List1.Remove(temp);
}
0 голосов
/ 25 июня 2018

Вы можете удалить дубликаты, используя оператор Distinct .

Чтобы удалить дубликаты из чего-то вроде IList <>, вы можете сделать:

yourList.RemoveAll( yourList.Except( yourList.Distinct() ) );
...