none
Как удалить все одинаковые числа в отсортированом списке ArrayList RRS feed

  • Вопрос

  • Всем Здравствуйте.У меня вопрос:

    Если у меня есть большой  список обьектов  (в моем случае ArrayList,обьекты типа int), как удалить одинаковые элементы?

    Посоветуйте каке есть способы?

    Зарание благодарен!

     

     

     

    • Перемещено Tagore Bandlamudi 1 октября 2010 г. 21:11 MSDN Forums consolidation (От:Visual C#)
    13 сентября 2010 г. 20:28

Ответы

  •       //Прямой способ - руками, предполагаю, что список отсортирован в неубывающем порядке
          ArrayList al1 = new ArrayList { 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4 };
    
          int index = 0;
          while(index < al1.Count- 1)
          {
            if ((int)al1[index] == (int)al1[index + 1])
            {
              al1.RemoveAt(index + 1);
            }
            else
            {
              index++;
            }
          }
    
          foreach (var item in al1)
          {
            Console.WriteLine(item);
          }
    
          Console.WriteLine("------------------------------------");
          //Изящный способ через Linq
          ArrayList al2 = new ArrayList { 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4 };
          var result = al2.ToArray().Distinct().ToList();
          foreach (var item in result)
          {
            Console.WriteLine(item);
          }
    
    • Предложено в качестве ответа userdab 23 сентября 2010 г. 23:07
    • Помечено в качестве ответа I.Vorontsov 28 сентября 2010 г. 8:16
    14 сентября 2010 г. 10:15

Все ответы

  •       //Прямой способ - руками, предполагаю, что список отсортирован в неубывающем порядке
          ArrayList al1 = new ArrayList { 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4 };
    
          int index = 0;
          while(index < al1.Count- 1)
          {
            if ((int)al1[index] == (int)al1[index + 1])
            {
              al1.RemoveAt(index + 1);
            }
            else
            {
              index++;
            }
          }
    
          foreach (var item in al1)
          {
            Console.WriteLine(item);
          }
    
          Console.WriteLine("------------------------------------");
          //Изящный способ через Linq
          ArrayList al2 = new ArrayList { 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4 };
          var result = al2.ToArray().Distinct().ToList();
          foreach (var item in result)
          {
            Console.WriteLine(item);
          }
    
    • Предложено в качестве ответа userdab 23 сентября 2010 г. 23:07
    • Помечено в качестве ответа I.Vorontsov 28 сентября 2010 г. 8:16
    14 сентября 2010 г. 10:15
  • Не понимаю зачем вообще использовать ArrayList который оперирует object, когда есть List<T> (если ты конечно не работаешь под .NET 2)

    Вот метод расширения для ArrayList (правда он вынужден работать с ограничениями накладываемыми ArrayList):

    static class ArrayListHelper
    {
     /// <summary>
     /// Удаляет дублированные объекты, в отсортированном списке
     /// </summary>
     /// <param name="_this">Экземпляр объекта ArrayList</param>
     /// <returns>Количество элементов в списке после удаления дубликатов</returns>
     public static int RemoveDuplicates(this ArrayList _this)
     {
      int d = 1;
      for (int s = 1; s < _this.Count; s++)
      {
       if (s != d && !_this[s].Equals(_this[d - 1]))
        _this[d++] = _this[s];
      }
      return d;
     }
    }
    

     

    Метод не элегантный, но не требует выделение лишней память

    • Предложено в качестве ответа userdab 23 сентября 2010 г. 23:06
    14 сентября 2010 г. 10:24
  • Не понимаю зачем вообще использовать ArrayList который оперирует object, когда есть List<T> (если ты конечно не работаешь под .NET 2)

    Вот метод расширения для ArrayList (правда он вынужден работать с ограничениями накладываемыми ArrayList):

    static class ArrayListHelper
    
    {
    
     /// <summary>
    
     /// Удаляет дублированные объекты, в отсортированном списке
    
     /// </summary>
    
     /// <param name="_this">Экземпляр объекта ArrayList</param>
    
     /// <returns>Количество элементов в списке после удаления дубликатов</returns>
    
     public static int RemoveDuplicates(this ArrayList _this)
    
     {
    
     int d = 1;
    
     for (int s = 1; s < _this.Count; s++)
    
     {
    
      if (s != d && !_this[s].Equals(_this[d - 1]))
    
      _this[d++] = _this[s];
    
     }
    
     return d;
    
     }
    
    }
    
    

     

    Метод не элегантный, но не требует выделение лишней память


    Подправь этот алгоритм, на границах списка неправильно работает
    14 сентября 2010 г. 12:01
  • Можно попробовать так:

    for (int i = 0; i < list.Count; i++)
          {
            for (int j = i + 1; j < list.Count; j++)
            {
              if (list[i].Equals(list[j]))
              {
                list.RemoveAt(j--);
              }
            }
          }
    
    Вроде работает, классический алгоритм.
    • Предложено в качестве ответа mtComsCxStart 20 сентября 2010 г. 13:57
    20 сентября 2010 г. 13:24
  • Всем Здравствуйте.У меня вопрос:

    Если у меня есть большой  список обьектов  (в моем случае ArrayList,обьекты типа int), как удалить одинаковые элементы?

    Посоветуйте каке есть способы?

    Зарание благодарен!

     

     

     

    ArrayList al1 = new ArrayList(new ArrayList { 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4 }.Cast<int>().Distinct().ToArray());
    
    п.с. это если используется .Net Framework 3.5 SP1 или выше.
    20 сентября 2010 г. 17:36
  • не катит, этот способ был во-первых уже описан мной в первом ответе,  во вторых он неээффективен по затратам памяти, придумывай новый:)

    На самом деле из представленных способов самый лучший это способ от Kaerus, он эффективен - требует одного прохода по списку и не нужно дополнительных затрат памяти, правда там нужно держать "указатель на конец обновленного списка",  что несколько запутывает, а также нужно подправить начальные условия.

    Мой первый способ удобен в смысле понимания, но очень медленный при большом количестве совпадений, т.к. он не сдвигает а физически даляет элементы, что происходит посредством копирования в новый массив, также работает и готовый Linq вариант.

    Поэтому если списки из сотен тысяч и миллионов элементов и операции будут происходить часто, то остановился бы на способе Каеруса, в случае малых списков остановился бы на способе через Linq

    20 сентября 2010 г. 18:24
  • Я случайно привел алгоритм, который может работать не только в отсортированном списке, но зато он универсальнее :)
    20 сентября 2010 г. 19:02
  • Я случайно привел алгоритм, который может работать не только в отсортированном списке, но зато он универсальнее :)


    хм, посмотри на мой первый ответ

    var result = al2.ToArray().Distinct().ToList();
    
    
    ..правда слишком круто называть это алгоритмом, это просто вызов метода расширения
    
    20 сентября 2010 г. 20:32