Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Сортировка массива записей по произвольному полю записи / 25 сообщений из 43, страница 1 из 2
31.05.2021, 08:59
    #40074256
antox
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сортировка массива записей по произвольному полю записи
Есть запись

Код: pascal
1.
2.
3.
4.
5.
TMyRec = record
  field1,
  field2,
  field3: string;
end;



Есть массив

Код: pascal
1.
a: array of TMyRec;



есть его сортировка

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
for i:=1 to n-1 do
for j:=i+1 to n do
  if a[i].field1>a[j].field1 then
    begin
       tmp:=a[i];
       a[i]:=a[j];
       a[j]:=tmp;
    end;



Как (с помощью крутых и новейших технологий Delphi) вместо field1 подставлять любое поле, чтобы не размножать сортировку для каждого поля в коде? :)
...
Рейтинг: 0 / 0
31.05.2021, 09:01
    #40074257
Gerasimenko
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сортировка массива записей по произвольному полю записи
antox,

передавать индекс сортируемого поля как параметр
...
Рейтинг: 0 / 0
31.05.2021, 09:07
    #40074262
x1ca4064
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сортировка массива записей по произвольному полю записи
antox

Как (с помощью крутых и новейших технологий Delphi) вместо field1 подставлять любое поле, чтобы не размножать сортировку для каждого поля в коде? :)


Передавать в сортировку функцию сравнения:

function Cmp(a,b:pointer):integer
...
Рейтинг: 0 / 0
31.05.2021, 09:16
    #40074265
antox
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сортировка массива записей по произвольному полю записи
Gerasimenko
antox,

передавать индекс сортируемого поля как параметр


а как обратиться по индексу?

Код: pascal
1.
a[i].field1>a[j].field1



или писать Case на все случаи?

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
case indx of
0: begin
  for i:=1 to n-1 do
  for j:=i+1 to n do
    if a[i].field1>a[j].field1 then
      begin
         tmp:=a[i];
         a[i]:=a[j];
         a[j]:=tmp;
      end;
1: begin
  for i:=1 to n-1 do
  for j:=i+1 to n do
    if a[i].field2>a[j].field2 then
      begin
         tmp:=a[i];
         a[i]:=a[j];
         a[j]:=tmp;
      end;
2: begin
  for i:=1 to n-1 do
  for j:=i+1 to n do
    if a[i].field3>a[j].field3 then
      begin
         tmp:=a[i];
         a[i]:=a[j];
         a[j]:=tmp;
      end;
end;



Можно как-то хотя бы через указатели (не знаю, как это сделать)?

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
 fld : point;
begin
case indx of
0: fld := ^field1;
1: fld := ^field2;
2: fld := ^field2;
end;
  for i:=1 to n-1 do
  for j:=i+1 to n do
    if a[i].fld^ >a[j].fld^ then
      begin
         tmp:=a[i];
         a[i]:=a[j];
         a[j]:=tmp;
      end;
end;
...
Рейтинг: 0 / 0
31.05.2021, 09:18
    #40074268
antox
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сортировка массива записей по произвольному полю записи
x1ca4064
antox

Как (с помощью крутых и новейших технологий Delphi) вместо field1 подставлять любое поле, чтобы не размножать сортировку для каждого поля в коде? :)


Передавать в сортировку функцию сравнения:

function Cmp(a,b:pointer):integer


А как это реализовать на примере?
...
Рейтинг: 0 / 0
31.05.2021, 09:21
    #40074269
Gerasimenko
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сортировка массива записей по произвольному полю записи
antox,

Код: pascal
1.
2.
3.
4.
5.
TMyRec = record
  field1,
  field2,
  field3: string;
end;



vs

Код: pascal
1.
2.
3.
TMyRec = record
  field: array [0..2] of string;
end;
...
Рейтинг: 0 / 0
31.05.2021, 09:27
    #40074271
antox
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сортировка массива записей по произвольному полю записи
Gerasimenko,

Так неудобно обращаться к полям :) Это можно запутаться, где чё хранится
...
Рейтинг: 0 / 0
31.05.2021, 09:39
    #40074276
x1ca4064
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сортировка массива записей по произвольному полю записи
antox

А как это реализовать на примере?


Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
type
  TCmpFun=function (a,b:pointer):integer;

function Cmp1(a,b:pointer):integer;
begin
  if TMyRec(a^).field1>TMyRec(b^).fileld1 then Result=1
  else if TMyRec(a^).field1<TMyRec(b^).fileld1 then Result:=-1
  else Result:=0;
end;

procedure MySort(Data:array of TMyRec;CmpFun:TCmpFun);
begin
  ....
  case CmpFun(@Data[i],@Data[j]) of
  -1:
    ....
  1:
    ...
  end;
end;

begin
  MySort(Data,@Cmp1);
end.



Можно и без указателей, если не нужна универсальность сортировки
...
Рейтинг: 0 / 0
31.05.2021, 09:56
    #40074284
antox
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сортировка массива записей по произвольному полю записи
x1ca4064,

Код: sql
1.
2.
3.
4.
5.
6.
function Cmp1(a,b:pointer):integer;
begin
  if TMyRec(a^).field1>TMyRec(b^).fileld1 then Result=1
  else if TMyRec(a^).field1<TMyRec(b^).fileld1 then Result:=-1
  else Result:=0;
end;



Так тут все равно напрямую указано имя поля field1 , а мне что бы по любому имени, или имеется в виду, что для каждого поля будет такая функция:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
function sField1(a,b:pointer):integer;
begin
  if TMyRec(a^).field1>TMyRec(b^).fileld1 then Result=1
  else if TMyRec(a^).field1<TMyRec(b^).fileld1 then Result:=-1
  else Result:=0;
end;

function sField2(a,b:pointer):integer;
begin
  if TMyRec(a^).field2>TMyRec(b^).fileld2 then Result=1
  else if TMyRec(a^).field2<TMyRec(b^).fileld2 then Result:=-1
  else Result:=0;
end;

function sField3(a,b:pointer):integer;
begin
  if TMyRec(a^).field3>TMyRec(b^).fileld3 then Result=1
  else if TMyRec(a^).field3<TMyRec(b^).fileld3 then Result:=-1
  else Result:=0;
end;
...
Рейтинг: 0 / 0
31.05.2021, 10:26
    #40074288
Fr0sT-Brutal
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сортировка массива записей по произвольному полю записи
antox
Так тут все равно напрямую указано имя поля field1 , а мне что бы по любому имени, или имеется в виду, что для каждого поля будет такая функция:

Чтобы не указывать, делай массив. Обращаться можно через именованные константы, чтобы не запутываться (rec.Fields[fField1]). Теоретически можно и через RTTI, но ты вряд ли осилишь на текущем уровне, раз уж такие вопросы задаешь
...
Рейтинг: 0 / 0
31.05.2021, 10:53
    #40074299
x1ca4064
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сортировка массива записей по произвольному полю записи
antox
x1ca4064,
Так тут все равно напрямую указано имя поля field1 , а мне что бы по любому имени, или имеется в виду, что для каждого поля будет такая функция:


Да, для каждого поля своя функция сравнения, ее прототип можно сделать таким:

TCmpFun=function (const a,b:TMyRec):integer;

но тогда будет тяжко написать общую процедуру сортировки, которая позволит сортировать почти все:

procedure MySort(const ArrayData;const ElementCount,ElementSize:integer;CmpFun:TCmpFun)
...
Рейтинг: 0 / 0
31.05.2021, 11:18
    #40074307
antox
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сортировка массива записей по произвольному полю записи
Fr0sT-Brutal
antox
Так тут все равно напрямую указано имя поля field1 , а мне что бы по любому имени, или имеется в виду, что для каждого поля будет такая функция:

Чтобы не указывать, делай массив. Обращаться можно через именованные константы, чтобы не запутываться (rec.Fields[fField1]). Теоретически можно и через RTTI, но ты вряд ли осилишь на текущем уровне, раз уж такие вопросы задаешь


Не благодари ;)

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
procedure Sort(field_name: string);
var
  i,j,n,f,findx: integer;
  val_i, val_j,  tmp: TMyRec;
  rtype: TRTTIType;
  fields: TArray<TRttiField>;
begin
  n:= High(A);

  rtype := TRTTIContext.Create.GetType(TypeInfo(TMyRec));
  fields := rtype.GetFields;

  findx:=-1;

  for f := Low(fields) to High(fields) do
    if fields[f].Name = field_name then findx := f;

  if findx < 0 then Exit;


  for i:=1 to n-1 do
  for j:=i+1 to n do
    begin
      val_i := a[i];
      val_j := a[j];

      if fields[findx].GetValue(@val_i).ToString > fields[findx].GetValue(@val_j).ToString then
        begin
          tmp:=a[i];
          a[i]:=a[j];
          a[j]:=tmp;
        end;
    end;
end;
...
Рейтинг: 0 / 0
31.05.2021, 12:14
    #40074327
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сортировка массива записей по произвольному полю записи
antox
Как (с помощью крутых и новейших технологий Delphi) вместо field1 подставлять любое поле
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
TArray.Sort<TMyRec>(a, TComparer<TMyRec>.Construct(
  function (const AItem1, AItem2: TMyRec): Integer
  begin
    Result := AnsiCompareStr(AItem1.Field1, AItem2.Field1);
  end;
));

TArray.Sort<TMyRec>(a, TComparer<TMyRec>.Construct(
  function (const AItem1, AItem2: TMyRec): Integer
  begin
    Result := AnsiCompareStr(AItem1.Field2, AItem2.Field2);
  end;
));
...
Рейтинг: 0 / 0
31.05.2021, 12:19
    #40074329
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сортировка массива записей по произвольному полю записи
Или
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
TMyRec = record
  field1,
  field2,
  field3: string;
  class function SortByField1(const AItem1, AItem2: TMyRec): Integer;
  class function SortByField2(const AItem1, AItem2: TMyRec): Integer;
end;

class function TMyRec.SortByField1(const AItem1, AItem2: TMyRec): Integer;
begin
   Result := AnsiCompareStr(AItem1.Field1, AItem2.Field1);
end;

class function TMyRec.SortByField2(const AItem1, AItem2: TMyRec): Integer;
begin
   Result := AnsiCompareStr(AItem1.Field2, AItem2.Field2);
end;

TArray.Sort<TMyRec>(a, TComparer<TMyRec>.Construct(TMyRec.SortByField1);
...
Рейтинг: 0 / 0
31.05.2021, 13:00
    #40074350
antox
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сортировка массива записей по произвольному полю записи
А вот они - новые технологии ;) Спасибо
...
Рейтинг: 0 / 0
31.05.2021, 13:06
    #40074352
antox
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сортировка массива записей по произвольному полю записи
_Vasilisk_
antox
Как (с помощью крутых и новейших технологий Delphi) вместо field1 подставлять любое поле
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
TArray.Sort<TMyRec>(a, TComparer<TMyRec>.Construct(
  function (const AItem1, AItem2: TMyRec): Integer
  begin
    Result := AnsiCompareStr(AItem1.Field1, AItem2.Field1);
  end;
));

TArray.Sort<TMyRec>(a, TComparer<TMyRec>.Construct(
  function (const AItem1, AItem2: TMyRec): Integer
  begin
    Result := AnsiCompareStr(AItem1.Field2, AItem2.Field2);
  end; //<- после end точку с запятой убрать
));



Работает отлично, точка с запятой лишняя
...
Рейтинг: 0 / 0
31.05.2021, 13:47
    #40074362
DimaBr
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сортировка массива записей по произвольному полю записи
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
for i:=1 to n-1 do
  for j:=i+1 to n do
    if (Index=0 and a[i].field1 > a[j].field1) or
       (Index=2 and a[i].field2 > a[j].field2) or
       (Index=3 and a[i].field3 > a[j].field3) then 
    begin
       tmp:=a[i];
       a[i]:=a[j];
       a[j]:=tmp;
    end;
...
Рейтинг: 0 / 0
31.05.2021, 13:58
    #40074368
antox
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сортировка массива записей по произвольному полю записи
_Vasilisk_
antox
Как (с помощью крутых и новейших технологий Delphi) вместо field1 подставлять любое поле
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
TArray.Sort<TMyRec>(a, TComparer<TMyRec>.Construct(
  function (const AItem1, AItem2: TMyRec): Integer
  begin
    Result := AnsiCompareStr(AItem1.Field1, AItem2.Field1);
  end;
));

TArray.Sort<TMyRec>(a, TComparer<TMyRec>.Construct(
  function (const AItem1, AItem2: TMyRec): Integer
  begin
    Result := AnsiCompareStr(AItem1.Field2, AItem2.Field2);
  end;
));



Модернизация под любое поле:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
procedure SuperSortArray(field_name: string);
var
  rtype: TRTTIType;
  fields: TArray<TRttiField>;
  f,findx: Integer;
  par_a, par_b: string;
begin
  rtype := TRTTIContext.Create.GetType(TypeInfo(TMyRec));
  fields := rtype.GetFields;

  findx:=-1;

  for f := Low(fields) to High(fields) do
    if fields[f].Name = field_name then findx := f;

  if findx < 0 then Exit;

  TArray.Sort<TFieldTovar>(a, TComparer<TMyRec>.Construct(
  function (const AItem1, AItem2: TMyRec): Integer
  begin
    par_a := fields[findx].GetValue(@AItem1).AsString;
    par_b := fields[findx].GetValue(@AItem2).AsString;
    Result := AnsiCompareStr(par_a, par_b);
  end
  ));
end;
...
Рейтинг: 0 / 0
31.05.2021, 14:04
    #40074369
DimaBr
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сортировка массива записей по произвольному полю записи
antox

Модернизация под любое поле:

А теперь для вещественных полей напишите
...
Рейтинг: 0 / 0
31.05.2021, 14:08
    #40074373
rgreat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сортировка массива записей по произвольному полю записи
Суровые извращения. Непонятно только зачем.
...
Рейтинг: 0 / 0
31.05.2021, 14:12
    #40074376
antox
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сортировка массива записей по произвольному полю записи
DimaBr
antox

Модернизация под любое поле:

А теперь для вещественных полей напишите


:( сортирует, как текст
...
Рейтинг: 0 / 0
31.05.2021, 14:14
    #40074377
antox
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сортировка массива записей по произвольному полю записи
rgreat
Суровые извращения. Непонятно только зачем.


Так, вроде, самый простой вариант сортировки массива записей по полям... Не знаю, как проще можно это сделать
...
Рейтинг: 0 / 0
31.05.2021, 14:20
    #40074384
antox
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сортировка массива записей по произвольному полю записи
DimaBr
antox

Модернизация под любое поле:

А теперь для вещественных полей напишите


Код: pascal
1.
2.
    //Result := AnsiCompareStr(par_a, par_b);
    Result := CompareValue(par_a, par_b);



Работает
...
Рейтинг: 0 / 0
31.05.2021, 14:20
    #40074385
DimaBr
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сортировка массива записей по произвольному полю записи
Куда проще ? 22329310
...
Рейтинг: 0 / 0
31.05.2021, 14:24
    #40074386
antox
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сортировка массива записей по произвольному полю записи
DimaBr,

Так для этого придется для сортировки каждого массива (а у них разные поля) писать все поля в процедуру :) Руки отвалятся

И так же тоже числа в сортируются как текст, как я понял
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Сортировка массива записей по произвольному полю записи / 25 сообщений из 43, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]