Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Подсчёт строк в TStringList

1.9K
01 августа 2004 года
xiOn
78 / / 16.03.2004
Есть задача подсчитать сколько повторных строк в TStringList и записать в Memo1 в виде "строка: кол-во"
Я сделал это 2мя способами но не один меня своей скоростью не устроил..
Вот первый:
Код:
for(int i = 0; i < list->Count; )
{
 int count = 1;
 str = list->Strings[i++];
 for(int j = i; j < list->Count; j++)
  if(str == list->Strings[j])
  {
   list->Delete(j);
   j--;
   count++;
  }
 Memo1->Lines->Add(str + ": " + IntToStr(count));
}

Вот второй сопсоб:
Код:
for(int i = 0; i < list->Count; )
{
 int count = 0;
 str = list->Strings[i++];
 for(;; )
  if(list->IndexOf(str) != -1){
   list->Delete(list->IndexOf(str));
   count++;}
  else break;
 Memo1->Lines->Add(str + ": " + IntToStr(count));
}

Который как ни странно на 30% медленее первого..
а листы в которых должен идти подсчёт строк очень и очень большие.
Пожалуйста помогите.. как можно сделать быстрее??
1.9K
01 августа 2004 года
xiOn
78 / / 16.03.2004
Для меня это очень важно..
Пожалуйста посоветуйте что нибуть
621
02 августа 2004 года
Бешеный кролик
151 / / 23.03.2004
Ну, например, можно избавиться от Delete и от вложенных циклов, хотя появится дополнительный внешний (кроме того, не стоит два раза вызывать IndexOf, наверное поэтому ваш второй метод работает дольше):

TList *numbers;
int *x,idx;

numbers=new TList();

for(int i=0; i<list->Count; i++)
{
x=new int(0); // Достаточно затратная операция
idx=list->IndexOf(list->Strings);
if(idx!= -1)
{
*(int *)numbers->Items[idx]++;
numbers->Add(x);
}
else
{
*x=1;
numbers->Add(x);
}
}

for(int i=0; i<list->Count; i++)
{
if (*(int *)numbers->Items!=0)
Memo1->Lines->Add(list->Items + ": " + IntToStr(*(int *)numbers->Items));

}
Вдруг будет быстрее? Напишите, может еще чего-нибудь придумаем.
621
02 августа 2004 года
Бешеный кролик
151 / / 23.03.2004
Можно даже в один проход и без дополнительного списка. Например, сразу класть строки в Memo в виде str : count, затем доставать count из строки и заменять ее новой:
str : count+1. Правда нужно будет вызывать функции обработки строк, поэтому может быть имеет смысл подумать об использовании какого-нибудь двухстолбцового компонента.
621
02 августа 2004 года
Бешеный кролик
151 / / 23.03.2004
Еще мысль, нельзя ли отсортировать список встроенным Sort'ом? Тогда задача тоже решается в один проход и без вложенных циклов (а также без доп списка, а соответственно без new и Add).
1.9K
02 августа 2004 года
xiOn
78 / / 16.03.2004
спасибо за помощ =))
Цитата:
два раза вызывать IndexOf, наверное поэтому ваш второй метод работает дольше):


Исправил ляп, вроде как процентов на 10 стало быстрее =)
Только я не смог заставить приведённый шикарный код верно работать из-за неправильной записи этой строки:
*(int *)numbers->Items[idx]++;
так даже не компилит, а так
*(int *)numbers->Items[idx] += 1;
компилит но выдаёт ошибку..

Цитата:
Еще мысль, нельзя ли отсортировать список встроенным Sort'ом? Тогда задача тоже решается в один проход и без вложенных циклов (а также без доп списка, а соответственно без new и Add).

Мысль смутно ясна и в тоже время нет =))
непонимаю как это можно сделать без вложенных циклов

621
02 августа 2004 года
Бешеный кролик
151 / / 23.03.2004
Цитата:
Originally posted by xiOn
спасибо за помощ =))

Исправил ляп, вроде как процентов на 10 стало быстрее =)
Только я не смог заставить приведённый шикарный код верно работать из-за неправильной записи этой строки:
*(int *)numbers->Items[idx]++;
так даже не компилит, а так
*(int *)numbers->Items[idx] += 1;
компилит но выдаёт ошибку..
Мысль смутно ясна и в тоже время нет =))
непонимаю как это можно сделать без вложенных циклов



Положим, что list у вас отсортирован, а значит все одинаковые строки располагаются друг за другом. Пишем код:

str=list->strings[0];
count=1;
for (i=1;i<list->Count;i++)
{
if (list->Strings==str) count++;
else
{
Вывод в Memo;
count=1;
str= list->Strings;
}
}

Единственный недостаток – строки в мемо будут в другом порядке, чем в исходном несортированном списке. Насчет первого алгоритма, раз уж вы его реализовали – попробуйте запустить (хотя бы временно сделайте v= *(int *)numbers->Items[idx]; v++; *(int *)numbers->Items[idx]=v; ) - мне интересно J

1.9K
02 августа 2004 года
xiOn
78 / / 16.03.2004
Ураа!!..
всё работает, я сделал тот что с сортировкой..
у меня на 100МБ лист ушло 60 секунд когда теме старыми способами что я делал ушло бы окола 1.5 часа! а тот способ что приводился кусок кода так и не удолось заставить работать верно, но это не важно.. важно что идея с сортировкой была очень хороша! Огромное спасибо!
621
02 августа 2004 года
Бешеный кролик
151 / / 23.03.2004
Цитата:
Originally posted by xiOn
Ураа!!..
всё работает, я сделал тот что с сортировкой..
у меня на 100МБ лист ушло 60 секунд когда теме старыми способами что я делал ушло бы окола 1.5 часа! а тот способ что приводился кусок кода так и не удолось заставить работать верно, но это не важно.. важно что идея с сортировкой была очень хороша! Огромное спасибо!



Рад, что помогло!

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог