Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2007.10.21;
Скачать: [xml.tar.bz2];

Вниз

Вот как можно ускорить программу?   Найти похожие ветки 

 
vasIZmax ©   (2007-09-28 23:53) [0]

Смысл ТЗ такой:
Есть два ини файла. В первом данные хранятся так
[Name]
id1=имя
id2=имя
...
id1000=имя
[Score]
id1=число
id2=число
...
id1000=число

А второй ини с данными о пользователе:
[User]
User=имя
[Score]
Score=число

Нужно вывести в СтрингГрид отсортированый ини1 по секции score, с учетом данных из ини2.
(грубо говоря, определить какое место среди всех записанных в ини2 будет занимать user из ини2, типо таблицы рейтинга).

Сделал все, но работает медленно. Хотелось бы ускорить. Ниже код с комментами.
//считаю сколько этих самых id в ини1
  d:=tstringlist.Create;
  ini := TIniFile.Create(extractfilepath(paramstr(0))+"\score\sco.ini");
  try
   begin
   ini.ReadSection("name",d);
   end;
  finally
   ini.Free;
  end;

//устанавливаю длины массивов, в ааа - для записывания чисел, а bbb - для имен  
  setlength(aaa,d.Count+1);
  setlength(bbb,d.Count+1);


//в переменные считываю данные о пользователе
  ini := TIniFile.Create(extractfilepath(paramstr(0))+"\user\"+form5.login+".ini");
  ballProm:=ini.ReadInteger("Ball","Ball",0);
  LoginProm:=ini.ReadString("Login","Login","");
  ini.Free;


//заполняю массивы
  ini := TIniFile.Create(extractfilepath(paramstr(0))+"\score\sco.ini");
  d1:=TstringList.Create;
  for i:=low(aaa) to high(aaa) do
  if i=0 then
  begin
  aaa[i]:=ballProm;
  bbb[i]:=LoginProm;
  d1.Add(inttostr(ballProm));
  end
  else
  begin
  aaa[i]:=ini.ReadInteger("Score","id"+inttostr(i),0);
  bbb[i]:=ini.ReadString("Name","id"+inttostr(i),"");
  d1.Add(ini.ReadString("Score","id"+inttostr(i),"0"));
  end;
  ini.Free;


//сортирую
  sort(aaa);

//вывожу в стринггрид.
  for i:=low(aaa) to high(aaa) do
  begin

//вывел число из отсортированного массива
form7.stringgrid1.Cells[0,i+1]:=inttostr(aaa[i]);
// сопоставляю числу его имя  
  for j:=low(aaa) to high(aaa) do
  if (aaa[i]=strtoint(d1.Strings[j])) then
  form7.stringgrid1.Cells[1,i+1]:=bbb[j];
  end;
  form7.StringGrid1.RowCount:=high(aaa)+1;
  form7.ShowModal;

//чищу память  
  aaa:=nil;
     bbb:=nil;
     d.Free;
     d1.Free;


Сортирую так:
procedure Sort(var A: array of Integer);
var
 I, J, T: Integer;
begin
 for I := Low(A)+1 to High(A) do
   for J := High(A) downto I + 1 do
     if A[I] > A[J] then
     begin
       T := A[I];
       A[I] := A[J];
       A[J] := T;
     end;
end;


Все работает, но надо б ускорить. Вопрос как? Или по другому не получится?

ЗЫ. Имхо, медлительность работы из-за вывода в стринггрид, покА он это все отобразит, поэтому так медленно.


 
Kolan ©   (2007-09-29 09:39) [1]

Считывай из Ini в лист и сортируй его средствами. Получишь QuickSort&#133


 
vasIZmax ©   (2007-09-29 17:56) [2]

хз, но не ускоряется все равно, по крайней мере заметна задержка появления формы...


 
Kolan ©   (2007-09-29 21:08) [3]

> хз, но не ускоряется все равно

Показывай как изменил&#133


 
vasIZmax ©   (2007-09-29 21:12) [4]

остановился на этом варианте
type ddd =  array of array of integer;

procedure TForm1.QuickSort(a: ddd; min, max: integer);
Var
i,j,mid, tmp, tmpName: integer;
Begin
if min<max then
begin
 mid:=A[0,min];
 i:=min-1;
 j:=max+1;
 while i<j do begin
   repeat
     i:=i+1;
     until A[0,i]>=mid;
   repeat
     j:=j-1;
     until A[0,j]<=mid;
   if i<j then begin
     tmp:=A[0,i];
     A[0,i]:=A[0,j];
     A[0,j]:=tmp;

     tmpName:=A[1,i];
     A[1,i]:=A[1,j];
     A[1,j]:=tmpName;
     end;
   end;
 QuickSort(a, min,j);
 QuickSort(a, j+1,max);
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
ini: TIniFile;
d,dName:Tstringlist;
LoginProm:string;
ballProm,i,j, T,t1: Integer;
aaa: ddd;
begin

d:=tstringlist.Create;
  ini := TIniFile.Create("\sco.ini");
  try
   begin
   ini.ReadSection("name",d);
   end;
  finally
   ini.Free;
  end;
  setlength(aaa,2,d.Count+1);

  ini := TIniFile.Create("\user.ini");
  ballProm:=ini.ReadInteger("Ball","Ball",0);
  LoginProm:=ini.ReadString("Login","Login","");
  ini.Free;

  dName:=Tstringlist.Create;
  ini := TIniFile.Create("\sco.ini");
  for i:=0 to d.Count do
  if i=0 then
  begin
  aaa[0,i]:=ballProm;
  aaa[1,i]:=i;
  dname.Add(LoginProm);
  end
  else
  begin
  aaa[0,i]:=ini.ReadInteger("Score","id"+inttostr(i),0);
  aaa[1,i]:=i;
  dname.Add(ini.ReadString("Name","id"+inttostr(i),"0"));
end;
  ini.Free;
      form1.QuickSort(aaa,0,d.Count);
      for I := 0 to high(aaa[0]) do
      begin
      form1.StringGrid1.Cells[0,i+1]:=inttostr(aaa[0,i]);
      form1.StringGrid1.Cells[1,i+1]:=dname.Strings[aaa[1,i]];
      end;
      form1.StringGrid1.RowCount:=d.Count+1;
end;


 
vasIZmax ©   (2007-09-29 21:17) [5]

И вариант о котором ты говорил(сразу не запостил, думал что удалил)
type Pdouble=^Integer;

function Comp(Item1, Item2:Pointer):integer;
begin
if PDouble(Item1)^<Pdouble(item2)^ then
result:=-1
else
if PDouble(Item1)^>Pdouble(item2)^ then
result:=1
else
result:=0;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
nows, last:Tdatetime;
k:integer;
List,listName:Tlist;
pd,ps:pdouble;
ini: TIniFile;
d,dName:Tstringlist;
LoginProm:string;
ballProm,i,j:integer;
begin
timer1.Enabled:=true;

d:=tstringlist.Create;
  ini := TIniFile.Create("\sco.ini");
  try
   begin
   ini.ReadSection("name",d);
   end;
  finally
   ini.Free;
  end;
  ini := TIniFile.Create("\user.ini");
  ballProm:=ini.ReadInteger("Ball","Ball",0);
  LoginProm:=ini.ReadString("Login","Login","");
  ini.Free;
  dName:=tstringlist.Create;
  ini := TIniFile.Create("\user.ini");
  list:=tlist.Create;
  listname:=tlist.Create;
  for i:=0 to d.Count do
  if i=0 then
  begin
New(pd);
New(ps);
Pd^:=ballProm;
ps^:=ballProm;
list.Add(pd);
listname.Add(ps);
dName.Add(LoginProm);
  end
  else
  begin
  New(pd);
  New(ps);
Pd^:=ini.ReadInteger("Score","id"+inttostr(i),0);
Ps^:=ini.ReadInteger("Score","id"+inttostr(i),0);
dName.Add(ini.ReadString("Name","id"+inttostr(i),""));
list.Add(pd);
listname.Add(ps);
end;
d.Free;
list.Sort(comp);

for k:=0 to list.Count-1 do
begin
pd:=list[k];
 for j:=0 to listname.Count-1 do
   begin
   ps:=listname[j];
     if pd^=ps^ then
       begin
         form1.StringGrid1.Cells[0,k+1]:=floattostr(pd^);
         form1.StringGrid1.Cells[1,k+1]:=dname.Strings[j];
         dispose(ps);
       end;
end;

dispose(pd);
end;
form1.StringGrid1.RowCount:=list.Count+1;
ini.Free;
list.Free;
listname.Free;
end;


 
Kolan ©   (2007-09-29 21:46) [6]

1. Я это прочесть не могу, сравни свой код с VCL и отформатируй по образцу.
2. Прорефакторь, что тут можно понять вообще, каша :(


 
Kolan ©   (2007-09-29 21:50) [7]

> И вариант о котором ты говорил(сразу не запостил, думал
> что удалил)

Работает? С указателями что-то ты перемудрил&#133


 
vasIZmax ©   (2007-09-29 21:58) [8]

так лучше? (с форматированием постоянно проблема:()
type ddd =  array of array of integer;

procedure TForm1.QuickSort(a: ddd; min, max: integer);
Var
i,j,mid, tmp, tmpName: integer;
Begin
if min<max then
begin
mid:=A[0,min];
i:=min-1;
j:=max+1;
while i<j do
  begin
    repeat
      i:=i+1;
    until A[0,i]>=mid;
    repeat
    j:=j-1;
    until A[0,j]<=mid;
    if i<j then
       begin
         tmp:=A[0,i];
         A[0,i]:=A[0,j];
         A[0,j]:=tmp;
         tmpName:=A[1,i];
         A[1,i]:=A[1,j];
         A[1,j]:=tmpName;
       end;
  end;
QuickSort(a, min,j);
QuickSort(a, j+1,max);
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
ini: TIniFile;
d,dName:Tstringlist;
LoginProm:string;
ballProm,i,j, T,t1: Integer;
aaa: ddd;

begin
d:=tstringlist.Create;
ini := TIniFile.Create("\sco.ini");
 try
   ini.ReadSection("name",d);
 finally
   ini.Free;
 end;

setlength(aaa,2,d.Count+1);

ini := TIniFile.Create("\user.ini");
 ballProm:=ini.ReadInteger("Ball","Ball",0);
 LoginProm:=ini.ReadString("Login","Login","");
ini.Free;

dName:=Tstringlist.Create;
ini := TIniFile.Create("\sco.ini");
 for i:=0 to d.Count do
 if i=0 then
   begin
     aaa[0,i]:=ballProm;
     aaa[1,i]:=i;
     dname.Add(LoginProm);
   end
 else
   begin
     aaa[0,i]:=ini.ReadInteger("Score","id"+inttostr(i),0);
     aaa[1,i]:=i;
     dname.Add(ini.ReadString("Name","id"+inttostr(i),"0"));
   end;
ini.Free;

form1.QuickSort(aaa,0,d.Count);

for I := 0 to high(aaa[0]) do
 begin
   form1.StringGrid1.Cells[0,i+1]:=inttostr(aaa[0,i]);
   form1.StringGrid1.Cells[1,i+1]:=dname.Strings[aaa[1,i]];
 end;

form1.StringGrid1.RowCount:=d.Count+1;
end;



> Kolan ©   (29.09.07 21:50) [7]

Работает.


 
Kolan ©   (2007-09-30 09:21) [9]

Нет, так тоже плохо.


> так лучше? (с форматированием постоянно проблема:()

http://www.citforum.ru/programming/delphi/style_delphi

Далее
1. Зачем самому делать QuickSort если он уже сделан: см. TList.Sort.
Более того он есть в TStringList.

2. Итого алгоритм примерно такой:

1. Загружаем секцию Name и секцию Souce в TStringList.
2. Теперь нужно подставить числа. Проходимся по списку с именами.
Для каждого имени загружаем ini пользователя вытаскиваем оттуда число и записываем в StringList с Source.

Какие надо сделать методы:
function LoadNames(IniFile: TIniFile): TStrings; //Можно передавать имя файла и создавать TIniFile внутри, но будет чуть дольше
function LoadScore(IniFile: TIniFile): TStrings;
function LoadUserValue(FileName, UserName: string): string;  //Если по имени файла не понять какой там пользователь, то придется загрузит все ини и искать внутри&#133


Для работы со строками типа A=B у StringList есть Names и Values.

Как только загрузил все что надо используй метод Sort.


 
sniknik ©   (2007-09-30 10:22) [10]

вот такая вот эпопея эмуляции 2х связанных таблиц через ж.. ээ.. инишники...

не лучше ли делать на том, что предназначено для обработки данных? таблицах/датасетах (если ini это из тз. то "вкачать" их в виртуальные детасеты и как угодно уже там объеденять/сортировать)


 
Slym ©   (2007-10-01 08:00) [11]

ТМеmInifile не быстрее?


 
Kolan ©   (2007-10-01 08:30) [12]

> вот такая вот эпопея эмуляции 2х связанных таблиц через
> ж&#133 ээ&#133 инишники&#133

Точно, ведь это две таблицыыы. Имхо, если длать именно через инишки, надо написать низкоуровнывее команда типа SELECT * FROM ini WHERE <&#133>
А потом пользуя их построить вызокоуровневые &#133


 
vasIZmax ©   (2007-10-01 13:12) [13]

> Kolan ©   (30.09.07 09:21) [9]

А если юзать sort при каждом добавлении score?

Я вот как алгоритм строил:
1. Считали данные с файла юзера и записал в StringList(это, я потом на двумерные динамиты перешел, но смысл не изменился) в string[0].
2. Потом считываю все необходимые данные из файла с общими данными.
3. Сортирую
4. Вывожу пользователю.


> sniknik ©   (30.09.07 10:22) [10]

ТЗ не сводится к конкретному использованию ini, а скорее к такому "делай как хочешь, главное быстро и надежно".
Для 1000 записей использовать датасеты... надо бут попробовать, посмотреть.



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2007.10.21;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.5 MB
Время: 0.064 c
15-1190456436
tmp
2007-09-22 14:20
2007.10.21
Просьба проверить код на Windows Vista


2-1190742234
Bast
2007-09-25 21:43
2007.10.21
Post


3-1176821654
Kostafey
2007-04-17 18:54
2007.10.21
Обновление значений полей взятых из присоединенной таблицы


2-1190968778
MM
2007-09-28 12:39
2007.10.21
счетчик


2-1190817616
Vitek2
2007-09-26 18:40
2007.10.21
Помогите с TabControl!





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский