Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 19.05.2016, 13:24   #1
garuna
Форумчанин
 
Аватар для garuna
 
Регистрация: 13.04.2013
Сообщений: 180
По умолчанию как ускорить сортировку массива записей

Есть массив записей, который нужно сортировать по дате. Использую для сортировки нижеприведенный код. Но он работает достаточно медленно, 1500 записей сортируются 10-15 секунд
Есть ли более быстрые способы сортировки? Или может можно как-то оптимизировать этот код? Спасибо за ответы.


Код:
type
 TLRec = record
  _1, _2, _3, _4, _5: string;
  end;
  TLArr = array of TLRec;

...

var
 ARR: TLArr;


procedure SortArrayList(var A: array of TLRec); // процедура сортировки
var
 i, j: integer;
 TempArr: TLRec;
begin
 for i:= 0 to Length(A)-1 do
 for j:= 0 to Length(A)-2 do
 begin
  if StrToDateTime(A[j]._1) < StrToDateTime(A[j+1]._1)  //сортируем по дате
  then
  begin
   TempArr:= A[j];
   A[j]:= A[j+1];
   A[j+1]:= TempArr;
  end;
 end;
end;

...

SortArrayList(ARR);

Последний раз редактировалось garuna; 19.05.2016 в 13:28.
garuna вне форума Ответить с цитированием
Старый 19.05.2016, 13:30   #2
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Использовать нормальный алгоритм сортировки вместо пузырьковой сортировки. + не конвертировать строки в дату во время сортировки, а сразу хранить не в виде строк.
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.

Последний раз редактировалось Alex11223; 19.05.2016 в 13:33.
Alex11223 вне форума Ответить с цитированием
Старый 19.05.2016, 13:32   #3
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

для начала изменить код сортировки на такой:
Код:
 for i:= 0 to Length(A)-2 do
 for j:= i+1 to Length(A)-1 do
 begin
  if StrToDateTime(A[j]._1) < StrToDateTime(A[j+1]._1)  //сортируем по дате
  then
  begin
   TempArr:= A[j];
   A[j]:= A[j+1];
   A[j+1]:= TempArr;
  end;
 end;
если это не даст большого выигрыша, ещё ускорим!
Serge_Bliznykov вне форума Ответить с цитированием
Старый 19.05.2016, 13:38   #4
IliaIT
Форумчанин
 
Аватар для IliaIT
 
Регистрация: 17.03.2009
Сообщений: 977
По умолчанию

по мне так главный тормоз StrToDateTime проще переделать сразу DT на входе, а потом в строку на выходе.
в цикле работать только с типом времени.
Интуитивно понятный интерфейс - это такой интерфейс, для работы с которым нужна недюжинная интуиция.
IliaIT вне форума Ответить с цитированием
Старый 19.05.2016, 13:53   #5
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

Цитата:
Сообщение от Alex11223 Посмотреть сообщение
+ не конвертировать строки в дату во время сортировки, а сразу хранить не в виде строк.
Цитата:
Сообщение от IliaIT Посмотреть сообщение
по мне так главный тормоз StrToDateTime проще переделать сразу DT на входе, а потом в строку на выходе.
в цикле работать только с типом времени.
с этим полностью согласен!

если этого будет мало - то индексировать только ссылки на запись - не меняя в цикле многократно множество строк (которые могут быть весьма объёмными, к слову!)
Serge_Bliznykov вне форума Ответить с цитированием
Старый 19.05.2016, 13:57   #6
Dvoishnik
Форумчанин
 
Регистрация: 12.02.2011
Сообщений: 808
По умолчанию

если нечего не напутал можно еще так причесать массив
чуть чуть быстрее чем пузырьком.
Код:
m:=Length(A)
k:=m
While (k>2) or flag do
	 Begin
		if k>2 then
			k:=round(k/1.24733095) ;
		flag:=false;
        i:=1;
		While (i+k-1 <= m) do
		 begin   
			if StrToDateTime(A[j]._1) < StrToDateTime(A[[i+k-1]._1) then
			 begin
				TempArr:=A[i+k-1];
				A[i+k-1]:=A[i];
				A[i]:=TempArr;
				flag:=true;
			 end;
			inc(i)
		 end;
	 end;
Терпение!Дежурный экстрасенс скоро свяжется с вами!

Последний раз редактировалось Dvoishnik; 19.05.2016 в 14:07.
Dvoishnik вне форума Ответить с цитированием
Старый 19.05.2016, 14:00   #7
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Щас ТС скопипастит из #3 и будет крик, что не работает. Чуть подправил код Сержа
Код:
for i:= 0 to Length(A)-2 do
 for j:= i+1 to Length(A)-1 do
 begin
  if StrToDateTime(A[j]._1) < StrToDateTime(A[i]._1)  //сортируем по дате
  then
  begin
   TempArr:= A[i];
   A[i]:= A[j];
   A[j]:= TempArr;
  end;
 end;
Да, не сомневаюсь, что основной тормоз - кудрявый цикл в #1, ну и символьная дата, но это вторично
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 19.05.2016, 14:08   #8
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

С 2009 в Дельфи вроде ж завезли TArray<T>.Sort http://docs.embarcadero.com/products...rray_of_T.html кроме Sort у TList.
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 19.05.2016, 14:08   #9
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

концептуально это может выглядеть так:
Код:
type TIndexRec = record
 index : integer,
 dt : TDateTime
end; 
var
  AIdx : array of TIndexRec;
  tmp : TIndexRec;
  i,j, n : integer;
begin
  n := Length(A)
  SetLength(AIdx, n);
  for i:=0 to n-1 do with AIndx[i] do begin
    index := i;
    dt := StrToDateTime(A[i]);
  end;

  for i:=0 to n-2 do
    for j:=i+1 to n-1 do 
      if AIdx[i].dt < AIndx[j].dt then begin tmp := AIdx[i]; AIdx[i]:=AIdx[j]; AIdx[j]:=tmp end;
  
  // фактически всё - массив индексов отсортирован. По нему можно отсортировать исходный массив.
  //  а можно и использовать его для вывода записей в нужном порядке, не трогая исходный массив.
  
end;

Аватар, да! Точно так. Накосячил я! Спасибо!

Alex11223, это верно. Вполне возможно (если у ТС современная версия Дельфи) - это подходящий вариант!

Последний раз редактировалось Serge_Bliznykov; 19.05.2016 в 14:10.
Serge_Bliznykov вне форума Ответить с цитированием
Старый 19.05.2016, 14:21   #10
garuna
Форумчанин
 
Аватар для garuna
 
Регистрация: 13.04.2013
Сообщений: 180
Счастье

А ведь действительно, избавился от StrToDateTime и стало НАМНОГО быстрее сортировать! =)

За коды благодарю, сейчас буду пробовать, может удастся еще больше ускорить)

Версия да, современная, XE3, только не совсем понял как в моем случае через TArray.Sort отсортировать, подкиньте примерчик если не сложно
garuna вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Сортировка как заставить код формировать сортировку по месту расположения верхней строки сортируемого массива Trimbl Microsoft Office Excel 1 29.04.2016 07:27
Реализовать сортировку массива записей Tuns Помощь студентам 0 26.05.2014 15:51
Не знаю как реалтзовать сортировку массива (Паскаль) WRNWRN Помощь студентам 7 20.12.2010 22:07
Запрос на сортировку записей по должности? Azeripatriot Microsoft Office Access 5 26.04.2010 17:06