Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Сортировка по столбцу


Автор: MerCus 1.10.2008, 03:24
есть таблица со значениями StringGrid, нужно отсортировать эти значения по столбцу (пусть будет столбец А), то есть один столбец(А) сортируем по возрастанию, а значения остальных столбцов сортируются соответственно значениям столбца А.
в Ecxel'e есть такая сортировка, думаю многие с ней знакомы. надо тоже самое организовать в StringGrid'е. может вопрос ламерский, но разобраться не могу, помогите пожалуйста! заранее спасибо!

Автор: MerCus 1.10.2008, 04:02
вот код который пишу я:
Код

repeat
    Flag2:=False;
    for k:=1 to n1-1 do begin
      if arg[k]>arg[k+1] then
       begin
       d1:=k;
        mi1:= arg[k];
        arg[k]:=arg[k+1];
        arg[k+1]:=mi1;
        For j:=1 to n2 do begin
            mi2:=a[j,d1];
            a[j,d1]:=a[j,d1+1];
            a[j,d1+1]:=mi2;
        end;
        Flag2:=True;
       end;
       end;
  until Flag2=False;


надо было пояснение написать..
так вот arg - это массив столбца в котором производим сортировку по возрастанию, а- это двумерный массив всех значений СтрингГрида.

Автор: Staruha 1.10.2008, 10:52
В StringGride есть свойство Index наверно это то что тебе надо

Автор: MerCus 2.10.2008, 00:38
не знаю, что вы имели ввиду, но свойства Индекс у СтрингГрида нет, если вы хотели мне сказать, что менять значения надо по соответствующим индексам, то я догодался и сам об этом, только у меня не выходит грамотно это прописать, поэтому я и обратился за помощью smile 

Автор: Staruha 2.10.2008, 11:57
Цитата

но свойства Индекс у СтрингГрида 

 smile действительно нет

Я по твоему образу написала код но он ругается на StringGrid1Sells[i-1,0];
наверно потому что String не заполнен.
Код

procedure TForm1.Button1Click(Sender: TObject);
 var
Flag2:boolean;
k,n1,i:integer;
mi1:String;
myarray:array[1..7] of string;
begin
   for i := 1 to 7 do
       myarray[i]:=StringGrid1Sells[i-1,0];
repeat
//n1:=7;
    Flag2:=False;
    for k:=1 to 7 do begin
      if myarray[k,0]>myarray[k+1,0] then
         mi1:= myarray[k,0];
        myarray[k,0]:=myarray[k+1,0];
         myarray[k,0]:=mi1;
       StringGrid1Sells[k-1,0]:=StringGrid1Sells[k,0];
         StringGrid1Sells[k,0]:=mi1;



        Flag2:=True;
       end;
       end;
  until Flag2=False;


end;

end.

Автор: Poseidon 2.10.2008, 14:11
Цитата(Staruha @  2.10.2008,  11:57 Найти цитируемый пост)
наверно потому что String не заполнен.
нет. Потому что нужна точка и не правильно написано.

StringGrid1.Сells[i-1,0];

Автор: uranpro 2.10.2008, 15:56
Staruha,  smile  smile  за StringGrid1Sells, особенно за Sells ))

"ол рихтс!"- сказал студент-самоучка, изучающий английский язык, положив на стол газету "невс тимес"

Автор: MerCus 3.10.2008, 02:38
по существу ответа так и не было, больше ни у кого никаких мыслей нет?

Автор: Poseidon 3.10.2008, 09:03
Можно либо делать сортировку в ручную, запихивая всю таблицу в многомерный массив, либо использовать другой компонент. К примеру, VirtualStringTree.

Автор: Staruha 3.10.2008, 11:12
MerCus нам немножко осталось до правильного решения.Я в коде все исправила больше не ругается только опять не могу тестировать.Вопрос Что в String данные тоже программно вводить?Чейто я не найду там ReadOnly

Код

procedure TForm1.Button1Click(Sender: TObject);
 var
Flag2:boolean;
k,n1,i:integer;
mi1:String;
myarray:array[1..7] of string;
begin
   for i := 1 to 7 do
       myarray[i]:=StringGrid1.Cells[i-1,0];
repeat
//n1:=7;
    Flag2:=False;
    for k:=1 to 7 do begin
      if myarray[k]>myarray[k+1] then
         mi1:= myarray[k];
        myarray[k]:=myarray[k+1];
         myarray[k]:=mi1;
       StringGrid1.Cells[k-1,0]:=StringGrid1.Cells[k,0];
         StringGrid1.Cells[k,0]:=mi1;

        Flag2:=True;
       end;

  until Flag2=False;


end;

end.

Автор: Staruha 3.10.2008, 11:50
OPtions.goEditing  люди добрые подсказали.

Сейчас че-нить накопаю

Автор: Staruha 3.10.2008, 14:40
Работает  smile 
Код

procedure TForm1.Button3Click(Sender: TObject);
  var
 flag:boolean;
k:integer;
mi1:String;
begin

  repeat
      flag:=false;
      for k := 1 to 6-1 do

      if StringGrid1.Cells[1,k]>StringGrid1.Cells[1,k+1] then
      Begin
         mi1:=StringGrid1.Cells[1,k];
        StringGrid1.Cells[1,k]:=StringGrid1.Cells[1,k+1];
         StringGrid1.Cells[1,k+1]:=mi1;

   flag:=true;
      end;
    until not flag;

        end;

Автор: THandle 4.10.2008, 09:57
Что то подобное:

Заполним StringGrid:

Код

procedure TForm1.Button1Click(Sender: TObject);
var
  I: Integer;
  J: Integer;
begin
  for I := 0 to StringGrid1.ColCount - 1 do
    for J := 0 to StringGrid1.RowCount - 1 do
      StringGrid1.Cells[I, J] := IntToStr(Random(1000));
end;


Сортируем:

Код

procedure TForm1.Button2Click(Sender: TObject);
var
  I: Integer;
  S: TStrings;
  J: Integer;
begin
  for I := 0 to StringGrid1.RowCount - 1 do
    for J := 0 to StringGrid1.RowCount - I - 2 do
      if CompareStr(StringGrid1.Cells[0, J], StringGrid1.Cells[0, J + 1]) > 0 then
        begin
          S := TStringList.Create;
          try
            S.Assign(StringGrid1.Rows[J]);
            StringGrid1.Rows[J].Assign(StringGrid1.Rows[J + 1]);
            StringGrid1.Rows[J + 1].Assign(S);
          finally
            S.Free;
          end;
        end;
end;


Сортирует СТРОКИ, а не числа, которые взяты просто для примера smile

Автор: MerCus 6.10.2008, 00:46
Staruha вы сортируете один столбец! это проще простого, а мне надо один столбец сортировать по возрастанию, а все остальные по этому столбцу.
THandle спасибо, но тоже не совсем то.

короче обьясняю как делаю я, и это скорее всего правильно, только наверное не совсем)))
делаем через массив, потом этот массив выводим в стринггрид. 
сортируем один столбец (который выбирает пользователь), запоминаем индекс числа в массиве которое меняем, и меняем числа в других столбцах с таким же индексом. собственно всё это отражает мой код во втором сообщении, а вы ребята, то ли меня не поняли, то ли от темы ушли. вы все к СтрингГриду прицепились, сортировать надо через массив, а потом его просто вывести.

Автор: Staruha 6.10.2008, 09:00
THandle 
Цитата

Сортирует СТРОКИ, а не числа, которые взяты просто для примера 

Я сама поражаюсь как это происходит ,но Строка в мною приведенном коде сортируется Супер ,а именно по первой букве ,по второй,третьей и т.д.

MerCus  
Цитата

Staruha вы сортируете один столбец! это проще простого

 спасибо тебе MerCus   smile 
 
так что получается,если  Stroka:=StringGrid1.Cells[1,k]+StringGrid1.Cells[2,k]+.....;
тоже должна сортироваться по тому же принципу. А массив или String(ты сам просил,хотя во всех примерах сортируются массивы) это просто контейнер.

Автор: THandle 6.10.2008, 09:27
Цитата(Staruha @  6.10.2008,  10:00 Найти цитируемый пост)
Я сама поражаюсь как это происходит ,но Строка в мною приведенном коде сортируется Супер ,а именно по первой букве ,по второй,третьей и т.д.


При сравнении 

Код

if StringGrid1.Cells[1,k]>StringGrid1.Cells[1,k+1] then


Вызывается функция UStrCmp, которая и сравнивает эти строчки smile


MerCus, зачем нужен массив, когда можно свободно обойтись без него. Не устраивает мой пример, тем что он сортирует по первому столбцу? Но ведь не сложно его изменить так чтоб он сортировал по любому другому smile Массив, ИМХО, тут только лишний.

Автор: MerCus 7.10.2008, 00:51
массив не лишний, по крайней мере для меня, так как я провожу основные работы именно с массивами, а Стринггрид просто для визуализации.
короче либо я тупой, но у меня ничего не получается))
мне строки то в принципе особо не нужны, у меня везде числа. ктонить попробуйте сделать такую сортировку с массивом.

спасибо всем за ответы, извините, что я туплю)) но мне это очень надо сделать, а у меня не получается

Автор: Staruha 8.10.2008, 08:15
сортируем String .Массив как буфер для ячеек по столбцам
Код

procedure TForm1.Button3Click(Sender: TObject);
  var
 flag:boolean;
k,i:integer;
mi1:array[1..3] of String;
begin

  repeat
      flag:=false;
      for k := 1 to 6-1 do
  Begin
       if StringGrid1.Cells[1,k]>StringGrid1.Cells[1,k+1] then//если число,strtoint(String.....
     Begin
        for i := 1 to 3 do

      Begin

         mi1[i]:=StringGrid1.Cells[i,k];
        StringGrid1.Cells[i,k]:=StringGrid1.Cells[i,k+1];
         StringGrid1.Cells[i,k+1]:=mi1[i];
      end;
   flag:=true;
    end;
    end;
   until not flag;

   end;

end.

Автор: THandle 8.10.2008, 11:15
Код

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Grids;

type
  TForm1 = class(TForm)
    StringGrid1: TStringGrid;
    Button1: TButton;
    Button2: TButton;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    procedure ShowArray;
    { Private declarations }
  public
    { Public declarations }
  end;

const
  ARRAY_SIZE = 5;

type
  TArray = array of array of Integer;

var
  Form1: TForm1;
  A: TArray;

implementation

{$R *.dfm}

procedure SortArray(var AArray: TArray; ANumber: Integer);

procedure Swap(AIndex1, AIndex2: Integer);
var
  I: Integer;
  Tmp: Integer;
begin
  for I := 0 to ARRAY_SIZE do
    begin
      Tmp := AArray[I, AIndex1];
      AArray[I, AIndex1] := AArray[I, AIndex2];
      AArray[I, AIndex2] := Tmp;
    end;
end;

procedure SwpNum;
  var
  I: Integer;
  Tmp: Integer;
begin
  for I := 0 to ARRAY_SIZE do
    begin
      Tmp := AArray[0, I];
      AArray[0, I] := AArray[ANumber, I];
      AArray[ANumber, i] := Tmp;
    end;
end;

procedure Sort;
var
  I, J: Integer;
begin
  for I := 0 to ARRAY_SIZE - 1 do
    for J := 0 to ARRAY_SIZE - 2 - I do
      if AArray[0, j] > AArray[0, j + 1] then
        Swap(J, J + 1);
end;

begin
  if not (ANumber in [0..ARRAY_SIZE - 1]) then
    Exit;
  SwpNum;
  Sort;
  SwpNum;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  I: Integer;
  J: Integer;
begin
  StringGrid1.ColCount := ARRAY_SIZE;
  StringGrid1.RowCount := ARRAY_SIZE;
  SetLength(A, ARRAY_SIZE, ARRAY_SIZE);
  for I := 0 to ARRAY_SIZE - 1 do
    for J := 0 to ARRAY_SIZE - 1 do
      A[I, J] := Random(10);
  ShowArray;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  Number: Integer;
begin
  if TryStrToInt(Edit1.Text, Number) then
    SortArray(A, Number);
  ShowArray;
end;

procedure TForm1.ShowArray;
var
  I: Integer;
  J: Integer;
begin
  for I := 0 to StringGrid1.ColCount - 1 do
    for J := 0 to StringGrid1.RowCount - 1 do
      StringGrid1.Cells[I, J] := IntToStr(A[I, J]);
end;

end.

Автор: Poseidon 8.10.2008, 12:51
Цитата(MerCus @  6.10.2008,  00:46 Найти цитируемый пост)
сортировать надо через массив, а потом его просто вывести.

Я тебе об этом писал в самом начале:
Цитата(Poseidon @  3.10.2008,  09:03 Найти цитируемый пост)
Можно либо делать сортировку в ручную, запихивая всю таблицу в многомерный массив, либо использовать другой компонент. 


Короче, вы мне надоели. Простую задачку расжовываете уже вторую страницу. Вот код (единственное условие - в гриде должны быть ТОЛЬКО числовые значение, что, собственно, оговаривалось выше).

Код

procedure SortStgingGrid(var StringGrid: TStringGrid;
                         const SortCol: Integer);
var mas: array of array of Integer;
x, y, buf: Integer;
Changed: boolean;
begin
  SetLength(mas, StringGrid.ColCount, StringGrid.RowCount);
  for y:= StringGrid.FixedRows to StringGrid.RowCount-1 do
    for x:= 0 to StringGrid.ColCount-1 do
    mas[x,y]:= StrToInt(StringGrid.Cells[x,y]);

  repeat
    Changed:= False;
    for y:= StringGrid.FixedRows to StringGrid.RowCount-2 do
      if mas[SortCol, y] > mas[SortCol, y+1] then
        for x:= 0 to StringGrid.ColCount-1 do
        begin
          buf:= mas[x, y];
          mas[x, y]:= mas[x, y+1];
          mas[x, y+1]:= buf;
          Changed:= True;
        end;
  until not Changed;

  for y:= StringGrid.FixedRows to StringGrid.RowCount-1 do
    for x:= 0 to StringGrid.ColCount-1 do
    StringGrid.Cells[x,y]:=IntToStr(mas[x,y]);
end;


Сортируем StringGrid1 по 2 столбцу (в функцию передаем 1, т.к. в гриде отсчет начинается с 0).
Код
procedure TForm1.Button1Click(Sender: TObject);
begin
  SortStgingGrid(StringGrid1, 1);
end;


Автор: THandle 8.10.2008, 14:22
Poseidon, первая строка у тебя вроде как не сортируется...

Кстати, чем мой код не устроил?

Автор: Poseidon 8.10.2008, 16:26
Цитата(THandle @  8.10.2008,  14:22 Найти цитируемый пост)
Poseidon, первая строка у тебя вроде как не сортируется...
Это от чего же?

Цитата(THandle @  8.10.2008,  14:22 Найти цитируемый пост)
чем мой код не устроил?
Чесно? Много букафффф smile Если ради одной сортировки делать глобальную переменную, обьявлять новый тип, да еще саму сортировку разбивать на 3 процедуры, то даже страшно будеть посмотреть на весь проект. А еще не нравится мне, что твоя сортировка привязана к ARRAY_SIZE. Т.е. ее не применишь для двух разных гридов. Мало того, ее не применишь для не "квадратных" гридов. Да и боюсь даже заикаться про фиксированные строки, которые де-факто не должны участвовать в сортировке (они на то и фиксированные).

Автор: MerCus 9.10.2008, 01:48
Всем спасибо за помощь! всё работает, всё понял))) 

Автор: THandle 9.10.2008, 02:02
MerCus, помечай тему как решенную.

Poseidon, не убедил)) у меня пример - пусть человек разбирается. У тебя готовое решение. Что лучше. Конечно же 1.  smile В любом случае получай плюс за потраченное время и помощь ТС.

Автор: Staruha 9.10.2008, 08:01
А мой код чем плох? Он такой маленький а сортирует не хуже ваших. smile 

Автор: Poseidon 9.10.2008, 08:28
Цитата(THandle @  9.10.2008,  02:02 Найти цитируемый пост)
у меня пример - пусть человек разбирается. У тебя готовое решение. Что лучше. Конечно же 1.
...и не поспоришь...

Добавлено через 14 минут и 35 секунд
Цитата(Staruha @  9.10.2008,  08:01 Найти цитируемый пост)
А мой код чем плох? Он такой маленький а сортирует не хуже ваших.
Ну... сама спросила smile :
  • Что если передаем таблицу отличную от размера 4х6 ?
  • Может я и придираюсь, но форматирование кода ужастное smile
  • Про фиксированные строки писать..?
  • Привязка к конкретному гриду
Это я, конечно, уже придираюсь. Если серьезно, то нормальный код. А если еще учесть что это пример, а не готовое решение, то сойдет smile

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