Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > .NET для новичков > Найти дубли в массиве


Автор: Suppir 17.1.2012, 14:12
Вводу строки в richTextBox1. Нужно найти одинаковые строки:

Код

string text = richTextBox1.Text;
string[] lines = text.Split('\n');

List<string> result = new List<string>();
    
Hashtable hash = new Hashtable();
            
foreach (string line in lines){
                
                if (hash.ContainsKey(line)){
                    result.Add(line + "\n");
                }
                else {
                    hash.Add(line, 1);
                }
            }
            
richTextBox1.Clear();

foreach (string line in result)
{
    richTextBox1.AppendText(line + "\n");
}



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

Автор: VSB 22.1.2012, 11:52
Код

richTextBox1.Lines=richTextBox1.Lines.GroupBy(i => i).Where(g => g.Count() > 1).Select(g => g.Key).ToArray();

Автор: Suppir 30.1.2012, 16:52
VSB, у меня проект под .NET Framework 2.0. В нем нет линка. 

Автор: diadiavova 30.1.2012, 23:51
Suppir, попробуй так
Код

        void RemoveLines()
        {
            List<string> result = new List<string>();
            foreach (string line in richTextBox1.Lines)
            {
                if (string.IsNullOrEmpty(result.Find(delegate(string s) { return s == line; }) )) result.Add(line);
            }
            richTextBox1.Clear();
            richTextBox1.AppendText(string.Join("\r\n",result.ToArray()));
        }

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

Автор: Suppir 31.1.2012, 08:19
в первом посте я пробовал а-ля Perl, поиск через хеш (если в хеше есть такой элемент, то выводим).

Код

@a = (1, 2, 3, 4, 1, 2);

foreach (@a){
    if ($hash{$_}++ == 1){
        print "$_\n"
    }
}



Автор: diadiavova 31.1.2012, 11:17
Цитата(Suppir @  31.1.2012,  09:19 Найти цитируемый пост)
в первом посте я пробовал а-ля Perl, поиск через хеш (если в хеше есть такой элемент, то выводим).

Как видишь в List<T> тоже есть метод, которым можно воспользоваться для этой цели. Кроме того, Hashtable - наследие первого фреймворка и там может быть потеря производительности хотябы даже на приведении типов. Ну и самое главное - ты много раз вызываешь AppendText, это видимо и есть основная проблема, а у меня этот метод вызывается только один раз.
ЗЫ
Ну и конечно же интересно было бы узнать, помогло или нет.

Автор: mihryak 31.1.2012, 11:52
Цитата(diadiavova @  31.1.2012,  12:17 Найти цитируемый пост)
Hashtable - наследие первого фреймворка и там может быть потеря производительности хотябы даже на приведении типов

Потери на приведении типов несравнимо меньше, чем пробег по коллекции со сравнением искомой строки с (потенциально) всеми остальными.
Хешированые коллекции требуют O(1) для поиска (для того, чтобы не получить потери на добавлении, нужно правильно задать изначальный Capacity, тогда и добавление будет O(1)), в отличие от O(N) у простого List<>.
Можно попробовать использовать Dictionary и сравнить его производительность с Hashtable.

Но несколько тысяч строк - вообще ни о чём, какая коллекция бы ни использовалась, поиск дублей будет мгновенным. Тут, как правильно ответил diadiavova, проблема скорее в многократный вызовах AppendText.

Автор: diadiavova 31.1.2012, 12:53
Цитата(mihryak @  31.1.2012,  12:52 Найти цитируемый пост)
Потери на приведении типов несравнимо меньше, чем пробег по коллекции со сравнением искомой строки с (потенциально) всеми остальными.

Ну я как бы и не предлагал сравнивать производительность List.Find и Hashtable.ContainsKey.

Автор: mihryak 31.1.2012, 12:59
Цитата(diadiavova @  31.1.2012,  13:53 Найти цитируемый пост)
Ну я как бы и не предлагал сравнивать производительность List.Find и Hashtable.ContainsKey

Ну ок, я просто увидел критику скорости Hashtable и использование List.Find вместо него, это выглядело как показ более подходящей альтернативы.

Кроме того. не стоит в этом видеть личный "наезд", я скорее отписался, потому что здесь - раздел "Для новичков", так что такое пояснение показалось не лишним.

Автор: diadiavova 31.1.2012, 13:12
Цитата(mihryak @  31.1.2012,  13:59 Найти цитируемый пост)
Ну ок, я просто увидел критику скорости Hashtable и использование List.Find вместо него, это выглядело как показ более подходящей альтернативы.

Да нет, я просто упомянул, что этот класс слегка устарел вот и все.
Цитата(mihryak @  31.1.2012,  13:59 Найти цитируемый пост)
Кроме того. не стоит в этом видеть личный "наезд"

И в мыслях не было, да и информация полезная и уместная.

Автор: VSB 3.2.2012, 18:07
diadiavova, и всё же, зачем тут вообще использовать небыстрый AppendText вместо создания списка строк и отправки его в richTextBox1.Lines ?
Suppir, а что не дает поднять уровень проекта до 3.5? 

Автор: diadiavova 3.2.2012, 19:38
Цитата(VSB @  3.2.2012,  19:07 Найти цитируемый пост)
diadiavova, и всё же, зачем тут вообще использовать небыстрый AppendText вместо создания списка строк и отправки его в richTextBox1.Lines ?

Не понял. Пример можно?

Автор: VSB 3.2.2012, 20:19
  
diadiavova, вместо 
richTextBox1.AppendText(string.Join("\r\n",result.ToArray()));
использовать сразу
richTextBox1.Lines=result.ToArray();

Автор: mihryak 9.2.2012, 18:54
VSB, твой код иначе работает - у топик стартера в RTB останется оригинальный текст, а под ним появятся найденные дубликаты; твой же код уберёт оригинальный текст
т.к. телепатов не бывает, вопросы о производительности по умолчанию подразумевают, что внешний результат останется тем же

Добавлено через 22 секунды
блин, на дату не посмотрел, простите

Автор: VSB 10.2.2012, 20:02
mihryak, нене у топикстартера есть richTextBox1.Clear(); и все равноЮ, лучше наверное делать Lines.Add() чем строки складывать. //впрочем, не мерил

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)