Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 28.01.2014, 06:55
royun royun вне форума
Прохожий
 
Регистрация: 19.08.2011
Сообщения: 28
Репутация: 10
По умолчанию Сравнение колонок StringGrid по строкам

Здравствуйте.
Есть StringGrid1 и в нем есть колонки КолA, КолB, кол-во повторов по строкам (см. вложения). Необходимо сделать:

1. сравнение по строкам, т.е. встречается ли пара StringGrid1.Cells[0,i], StringGrid1.Cells[1,i]
2. удалить повторы
3. вывести кол-во повторов

Код:
procedure TForm1.Button2Click(Sender: TObject);
var
kolvoAB, AllAB: array of integer;
i,j,k,kolAB, n: integer;
begin
n:=StringGrid1.RowCount;
SetLength(AllAB,n);
SetLength(kolvoAB,n);
for i:=1 to n do
    begin
    AllAB[i]:= StrToInt(StringGrid1.Cells[0,i]+StringGrid1.Cells[1,i]);
    end;
i:=1;
while i <= n  do
begin
kolAB:=1;
j:=i+1;
    while j <= n do
    begin
    if AllAB[i]=AllAB[j] then
      begin
      for k:=j to n-1 do AllAB[k]:=AllAB[k+1];
      kolAB:=kolAB+1;
      n:=n-1;
      end
    else j:=j+1;
    end;
kolvoAB[i]:=kolAB;
i:=i+1;
end;
StringGrid1.RowCount:=n;
for i := 1 to n do
StringGrid1.cells[2,i]:=IntToStr(kolvoAB[i]);
end;

Проблема заключается в том, что
1.ошибка "Invalid pointer operation" выскакивает на 33-й строке и данные до конца не отображаются
2.Как решить задачу, если массив AllAB это массив чисел int64
Изображения
Тип файла: png sg.png (17.8 Кбайт, 3 просмотров)
Тип файла: png sg1.png (27.2 Кбайт, 2 просмотров)

Последний раз редактировалось royun, 28.01.2014 в 07:16.
Ответить с цитированием
  #2  
Старый 28.01.2014, 08:01
royun royun вне форума
Прохожий
 
Регистрация: 19.08.2011
Сообщения: 28
Репутация: 10
По умолчанию

Исправил код и заработало:

Код:
procedure TForm1.Button2Click(Sender: TObject);
var
AllAB: array of int64;
kolvoAB: array of integer; 
i,j,k,kolAB, n: integer;
begin
n:=StringGrid1.RowCount;
SetLength(AllAB,n);
SetLength(kolvoAB,n);
for i:=1 to n-1 do
    begin
    AllAB[i]:= StrToInt64(StringGrid1.Cells[0,i]+StringGrid1.Cells[1,i]);
    end;
i:=1;
while i <= n  do
begin
kolAB:=1;
j:=i+1;
    while j <= n do
    begin
    if AllAB[i]=AllAB[j] then
      begin
      for k:=j to n-1 do AllAB[k]:=AllAB[k+1];
      kolAB:=kolAB+1;
      n:=n-1;
      end
    else j:=j+1;
    end;
kolvoAB[i]:=kolAB;
i:=i+1;
end;
StringGrid1.RowCount:=n;
for i := 1 to n-1 do
StringGrid1.cells[2,i]:=IntToStr(kolvoAB[i]);
KolvoAB:=nil;
AllAB:=nil;
end;

Если цифры в колонках 10-значные то вываливается ошибка "is not valid integer value" и это понятно: 20-значное число выходит за рамки int64.
Я понимаю что механизм сравнения у меня неправильный. И хотел бы послушать Ваши предложения.
Изображения
Тип файла: png err.png (18.1 Кбайт, 1 просмотров)
Ответить с цитированием
  #3  
Старый 28.01.2014, 11:16
Аватар для poli-smen
poli-smen poli-smen вне форума
Профессионал
 
Регистрация: 06.08.2012
Адрес: Кривой Рог
Сообщения: 1,791
Версия Delphi: Delphi 7, XE2
Репутация: 4415
По умолчанию

Цитата:
Сообщение от royun
Если цифры в колонках 10-значные то вываливается ошибка "is not valid integer value" и это понятно: 20-значное число выходит за рамки int64.
Работай со строками - у строк таких ограничений нет:
Код:
var
  AllAB: array of String;
Или объяви свой тип и сделай из него массив:
Код:
type
  TTwoCols = record
    Col1, Col2: Int64;
  end;
var
  AllAB: array of TTwoCols;
Цитата:
Сообщение от royun
Я понимаю что механизм сравнения у меня неправильный. И хотел бы послушать Ваши предложения.
Очевидно неправильный, например КолА="12", КолВ="3" и КолА="1", КолВ="23" будут засчитаны как идентичные, хотя такими не являются.
Ответить с цитированием
  #4  
Старый 29.01.2014, 09:30
royun royun вне форума
Прохожий
 
Регистрация: 19.08.2011
Сообщения: 28
Репутация: 10
По умолчанию

Если вдруг кому-то поможет. Вот решение:
Код:
procedure TForm1.Button2Click(Sender: TObject);
var
  TS : TStringList;
  i, indexS  : integer;
begin
  TS := TStringList.Create;
  for i:=1 to StringGrid1.RowCount-1 do begin
     indexS := TS.IndexOf(StringGrid1.Cells[2,i]);
     if indexS<0 then begin {ещё не было такой строки, добавляем}
        TS.AddObject(StringGrid1.Cells[2,i], TObject(1));
     end
     else {такое значение уже было ранее, увеличим счётчик на 1}
       TS.Objects[indexS] := TObject(Integer(TS.Objects[indexS])+1);
  end;

  StringGrid2.RowCount := TS.Count+1;
  for I := 0 to TS.Count - 1 do begin
    StringGrid2.Cells[0,i+1] := IntToStr(i+1);
    StringGrid2.Cells[1,i+1] := TS.Strings[i];
    StringGrid2.Cells[2,i+1] := IntToStr( Integer(TS.Objects[i]));
  end;

  FreeAndNil(TS);
end;
Ответить с цитированием
  #5  
Старый 29.01.2014, 11:03
Аватар для poli-smen
poli-smen poli-smen вне форума
Профессионал
 
Регистрация: 06.08.2012
Адрес: Кривой Рог
Сообщения: 1,791
Версия Delphi: Delphi 7, XE2
Репутация: 4415
По умолчанию

Цитата:
Сообщение от royun
Если вдруг кому-то поможет. Вот решение:
Код:
procedure TForm1.Button2Click(Sender: TObject);
var
  TS : TStringList;
  i, indexS  : integer;
begin
  TS := TStringList.Create;
Здесь ещё желательно сделать список сортированным:
Код:
TS.Sorted := True;
В сортированном списке поиск будет происходить значительно быстрее, особенно для больших списков.
Цитата:
Сообщение от royun
Код:
     else {такое значение уже было ранее, увеличим счётчик на 1}
       TS.Objects[indexS] := TObject(Integer(TS.Objects[indexS])+1);
С такими преобразованиями следует быть поосторожнее - здесь нужно помнить, что в 64-битных приложениях указатели стали 8-байтными, а тип Integer почему-то так и остался 4-байтным (как и был в 32-битных приложениях). И кроме того в последних версиях Delphi идёт тенденция к отказу от указателей, и такое скорее всего даже и не откомпилируется.
Цитата:
Сообщение от royun
Код:
  for I := 0 to TS.Count - 1 do begin
    StringGrid2.Cells[0,i+1] := IntToStr(i+1);
    StringGrid2.Cells[1,i+1] := TS.Strings[i];
    StringGrid2.Cells[2,i+1] := IntToStr( Integer(TS.Objects[i]));
  end;
Странно. Вроде в исходном задании нужно было отбирать уникальные значения по двум колонкам, а здесь отбирается только по одной. Так что это решение неполное.
Ответить с цитированием
  #6  
Старый 29.01.2014, 16:26
royun royun вне форума
Прохожий
 
Регистрация: 19.08.2011
Сообщения: 28
Репутация: 10
По умолчанию

Цитата:
Странно. Вроде в исходном задании нужно было отбирать уникальные значения по двум колонкам, а здесь отбирается только по одной. Так что это решение неполное.

StringGrid1.Cells[1,i]:=StringGrid1.Cells[2,i]+'='+StringGrid1.Cells[3,i]

Вот в таком виде решение полное.

Последний раз редактировалось royun, 29.01.2014 в 16:29.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра
Комбинированный вид Комбинированный вид

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 16:13.


 

Сайт

Форум

FAQ

Соглашения

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2025