Как удалить дубликаты в списке? - PullRequest
2 голосов
/ 16 мая 2011

Ну, мне нужно проверить, есть ли дубликаты элементов внутри списка в моем приложении, но ... я не знаю как.

Чтобы определить это, отметьте поле «Тег»., если они одинаковые, то удалите элемент.

Ответы [ 7 ]

5 голосов
/ 16 мая 2011

Хороший способ найти дубликаты - использовать временный хэшсет. Это дает вам алгоритм O(n) O(n log n) (см. Комментарии Рика Слэдкиса) для обнаружения дубликатов. Пример:

var tags = new HashSet<string>();
var duplicates = new List<Item>();

foreach(Item item in listView.Items)
{
    // HashSet.Add() returns false if it already contains the key.
    if(!tags.Add(item.Tag) 
        duplicates.Add(item);
}

[Remove duplicates here]
2 голосов
/ 17 апреля 2012

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

myListView - это ListView, отсортированный по алфавиту (поэтому дубликаты в этом случае соседние). Вы могли бы отсортировать это заранее программно, если хотите.

myListView.Sorting = SortOrder.Ascending;

В любом случае, это довольно упрощенно, но я надеюсь, что это кому-нибудь поможет!

for (int i = 0; i < myListView.Items.Count - 1; i++)
{
    if (myListView.Items[i].Tag == myListVIew.Items[i + 1].Tag)
    {
       myListView.Items[i + 1].Remove();
    }
}
2 голосов
/ 16 мая 2011

Используется для создания вложенных циклов и проверки каждого элемента по отношению друг к другу.

//tag duplicates for removal
List<Item> toRemove = new List<Item>();
foreach(Item item1 in listView.Items)
{
  foreach(Item item2 in listView.Items)
  {
    //compare the two items
    if(item1.Tag == item2.Tag)
      toRemove.Add(item2);
  }
}    

//remove duplicates
foreach(Item item in toRemove)
{
  listView.Items.Remove(item);
}

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

0 голосов
/ 02 февраля 2013
 int J = 0;

В этом простом коде мы удалим дубликаты из цикла, который возьмет первый элемент и сравнит его с нижеуказанными элементами, поэтому, если он существует, вы можете удалить указанный выше или второй

foreach (ListViewItem item1 in listView1.Items)
        {
             //J+1 to do not repeat the list from first and remove itself just take a look on next items              
            for (int i=J+1;i<listView1.Items.Count-1;i++) 
            {

                //i compare two subitems that must be unique in my list
                if (listView1.Items[J].SubItems[1].ToString() == listView1.Items[i].SubItems[1].ToString())

          // listView1.Items.RemoveAt(i); // remove the second one 
             listView1.Items.RemoveAt(J); // remove the first one and keep the second
            }
            J++;
        }
0 голосов
/ 24 августа 2011

Я хотел бы предложить свое решение, используя словарь для дальнейшего использования: (вы будете редактировать свои собственные "Colums" (подпункты), просто прочитайте код, чтобы понять.

Я использовал ниже для удаления"Dups" в просмотре списка по нажатию кнопки, я ищу подпункт, вы можете редактировать код для своего собственного использования ...

использует словарь и небольшой простой класс "update", который я написал.

private void removeDupBtn_Click(object sender, EventArgs e)
    {   

        Dictionary<string, string> dict = new Dictionary<string, string>();

        int num = 0;
        while (num <= listView1.Items.Count)
        {
            if (num == listView1.Items.Count)
            {
                break;
            }

            if (dict.ContainsKey(listView1.Items[num].SubItems[1].Text).Equals(false))
            {
                dict.Add(listView1.Items[num].SubItems[1].Text, ListView1.Items[num].SubItems[0].Text);
            }     

            num++;
        }

        updateList(dict, listView1);

    }

и используя небольшой класс updateList () ...

   private void updateList(Dictionary<string, string> dict, ListView list)
    {
        #region Sort
        list.Items.Clear();

        string[] arrays = dict.Keys.ToArray();
        int num = 0;
        while (num <= dict.Count)
        {
            if (num == dict.Count)
            {
                break;
            }

            ListViewItem lvi;
            ListViewItem.ListViewSubItem lvsi;

            lvi = new ListViewItem();
            lvi.Text = dict[arrays[num]].ToString();
            lvi.ImageIndex = 0;
            lvi.Tag = dict[arrays[num]].ToString();

            lvsi = new ListViewItem.ListViewSubItem();
            lvsi.Text = arrays[num];
            lvi.SubItems.Add(lvsi);

            list.Items.Add(lvi);

            list.EndUpdate();

            num++;
        }
        #endregion
    }

Удачи!

0 голосов
/ 21 мая 2011

Если вы сравниваете дублирующиеся элементы на основе определенных столбцов, вы должны просто использовать:

if(listview.Items.Find(SearchQuery).Count > 0)
{
   //remove duplicates from list...
}

, но вы должны назвать каждый элемент в списке при заполнении списка ... например, если я хочуискать дублирующиеся элементы в столбце 1 + 2 + 5, я назову всю строку следующим образом:

myItemName.Name = column1.Text + "_" + column2.Text + "_" + column5.Text;

, а затем выполню приведенное выше выражение "if" ..

0 голосов
/ 16 мая 2011

Если у вас много предметов, вы можете использовать HashSet для поддержания приемлемой производительности.

Зацикливание элементов, начиная с пустого HashSet. Для каждого элемента проверьте, есть ли тег в HashSet. Если так, то это дубликат. Если нет, добавьте тег в HashSet.

Этот подход позволяет избежать алгоритма N ^ 2, который вы получаете с помощью вложенного цикла. HashSet делает алгоритм линейной сложностью, обеспечивая тщательную реализацию фазы удаления. Конечно, это может не иметь значения для вас, в зависимости от того, сколько предметов у вас есть. Если список небольшой, используйте вложенные циклы и сделайте его простым.

...