AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Feld sortieren und damit weiterarbeiten

Ein Thema von Ultimator · begonnen am 1. Apr 2015 · letzter Beitrag vom 2. Apr 2015
 
Bjoerk

Registriert seit: 28. Feb 2011
Ort: Mannheim
1.384 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: Feld sortieren und damit weiterarbeiten

  Alt 1. Apr 2015, 17:25
Und natürlich wenn sich Count ändert. Am besten, man spielt es an einem konkreten Beispiel durch.

Ungetestet:

Delphi-Quellcode:
unit uSortedDaten;

interface

uses
  Windows, SysUtils, Dialogs, Classes, Math;

type
  TDatenItem = record
    Id: integer;
    Name: string;
  end;

  TDatenSortFlag = (dsfId, dsfName);

  TDaten = class
  private
    FItems: array of TDatenItem;
    FSorted: boolean;
    FSortFlag: TDatenSortFlag;
    FOnChange, FOnChanging: TNotifyEvent;
    function Get(Index: integer): TDatenItem;
    function GetCount: integer;
    procedure Put(Index: integer; const Value: TDatenItem);
    procedure SetCount(Value: integer);
    procedure SetSorted(const Value: boolean);
    procedure SortExchange(Index1, Index2: integer);
    function SortCompare(const A, B: TDatenItem): integer;
    procedure QuickSort(L, R: integer);
    procedure Changed;
    procedure Changing;
  public
    procedure Clear;
    procedure Add(const Value: TDatenItem);
    procedure Delete(Index: integer);
    procedure Insert(Index: integer; const Value: TDatenItem);
    procedure Exchange(Index1, Index2: integer);
    procedure Sort;
    function IndexOfID(Value: integer): integer;
    procedure Assign(Value: TDaten);
    procedure LoadFromFile(const FileName: string);
    procedure SaveToFile(const FileName: string);
    destructor Destroy; override;
    property Count: integer read GetCount;
    property Sorted: boolean read FSorted write SetSorted;
    property SortFlag: TDatenSortFlag read FSortFlag write FSortFlag;
    property OnChange: TNotifyEvent read FOnChange write FOnChange;
    property OnChanging: TNotifyEvent read FOnChanging write FOnChanging;
    property Items[Index: integer]: TDatenItem read Get write Put; default;
  end;

implementation

type
  TFileStreamEx = class(TFileStream)
  private
    function ReadAnsiString: AnsiString;
  public
    function ReadInteger: integer;
    function ReadString: string;
    procedure WriteInteger(const Value: integer);
    procedure WriteString(const Value: string);
  end;

{ procedural }

function Compare(const A, B: TDatenItem): boolean;
begin
  Result := (A.Id = B.Id) and (A.Name = B.Name);
end;

{ TDaten }

destructor TDaten.Destroy;
begin
  FOnChange := nil;
  FOnChanging := nil;
  Setlength(FItems, 0);
end;

procedure TDaten.Changed;
begin
  if FSorted then
    Sort;
  if Assigned(FOnChange) then
    FOnChange(Self);
end;

procedure TDaten.Changing;
begin
  if Assigned(FOnChanging) then
    FOnChanging(Self);
end;

procedure TDaten.Clear;
begin
  if Count <> 0 then
  begin
    Changing;
    SetLength(FItems, 0);
    Changed;
  end;
end;

procedure TDaten.Add(const Value: TDatenItem);
begin
  Insert(Count, Value);
end;

procedure TDaten.Delete(Index: integer);
var
  I: integer;
begin
  Changing;
  for I := Index to Count - 2 do
    FItems[I] := FItems[I + 1];
  SetCount(Count - 1);
  Changed;
end;

procedure TDaten.Exchange(Index1, Index2: integer);
var
  Temp: TDatenItem;
begin
  Changing;
  Temp := FItems[Index1];
  FItems[Index1] := FItems[Index2];
  FItems[Index2] := Temp;
  Changed;
end;

function TDaten.Get(Index: integer): TDatenItem;
begin
  Result := FItems[Index];
end;

function TDaten.GetCount: integer;
begin
  Result := Length(FItems)
end;

procedure TDaten.Insert(Index: integer; const Value: TDatenItem);
var
  I: integer;
begin
  Changing;
  SetCount(Count + 1);
  for I := Count - 1 downto Index + 1 do
    FItems[I] := FItems[I - 1];
  FItems[Index] := Value;
  Changed;
end;

procedure TDaten.Put(Index: integer; const Value: TDatenItem);
begin
  if not Compare(Value, FItems[Index]) then
  begin
    Changing;
    FItems[Index] := Value;
    Changed;
  end;
end;

procedure TDaten.SetCount(Value: integer);
begin
  SetLength(FItems, Value);
end;

procedure TDaten.SortExchange(Index1, Index2: integer);
var
  Temp: TDatenItem;
begin
  Temp := FItems[Index1];
  FItems[Index1] := FItems[Index2];
  FItems[Index2] := Temp;
end;

function TDaten.SortCompare(const A, B: TDatenItem): integer;
begin
  if FSortFlag = dsfName then
    Result := AnsiCompareText(A.Name, B.Name)
  else
    Result := CompareValue(A.Id, B.Id);
end;

procedure TDaten.QuickSort(L, R: integer);
var
  I, J, K: integer;
  Pivot: TDatenItem;
begin
  repeat
    I := L;
    J := R;
    K := (L + R) shr 1;
    Pivot := FItems[K];
    repeat
      while SortCompare(FItems[I], Pivot) < 0 do
        Inc(I);
      while SortCompare(FItems[J], Pivot) > 0 do
        Dec(J);
      if I <= J then
      begin
        SortExchange(I, J);
        Inc(I);
        Dec(J);
      end;
    until I > J;
    if L < J then
      QuickSort(L, J);
    L := I;
  until I >= R;
end;

procedure TDaten.Sort;
begin
  if Count > 1 then
    QuickSort(0, Count - 1);
end;

procedure TDaten.SetSorted(const Value: boolean);
begin
  if FSorted <> Value then
  begin
    Changing;
    FSorted := Value;
    Changed;
  end;
end;

function TDaten.IndexOfID(Value: integer): integer;
var
  I: integer;
begin
  Result := -1;
  for I := 0 to Count - 1 do
    if FItems[I].Id = Value then
    begin
      Result := I;
      Break;
    end;
end;

procedure TDaten.Assign(Value: TDaten);
var
  I: integer;
begin
  Clear;
  for I := 0 to Value.Count - 1 do
    Add(Value[I]);
end;

procedure TDaten.LoadFromFile(const FileName: string);
var
  Stream: TFileStreamEx;
  I, N: integer;
  Value: TDatenItem;
begin
  if FileExists(FileName) then
  begin
    Clear;
    Stream := TFileStreamEx.Create(FileName, fmOpenRead or fmShareDenyNone);
    try
      N := Stream.ReadInteger;
      for I := 0 to N - 1 do
      begin
        Value.Id := Stream.ReadInteger;
        Value.Name := Stream.ReadString;
        Add(Value);
      end;
    finally
      Stream.Free;
    end;
  end;
end;

procedure TDaten.SaveToFile(const FileName: string);
var
  Stream: TFileStreamEx;
  I: integer;
begin
  Stream := TFileStreamEx.Create(FileName, fmCreate);
  try
    Stream.WriteInteger(Count);
    for I := 0 to Count - 1 do
    begin
      Stream.WriteInteger(FItems[I].Id);
      Stream.WriteString(FItems[I].Name);
    end;
  finally
    Stream.Free;
  end;
end;

{ TFileStreamEx }

function TFileStreamEx.ReadInteger: integer;
begin
  ReadBuffer(Result, SizeOf(integer));
end;

function TFileStreamEx.ReadAnsiString: AnsiString;
var
  N: integer;
begin
  N := ReadInteger;
  SetLength(Result, N);
  if N > 0 then
    ReadBuffer(Result[1], N);
end;

function TFileStreamEx.ReadString: string; // need AnsiStringBuffer
begin
  Result := ReadAnsiString;
end;

procedure TFileStreamEx.WriteInteger(const Value: integer);
begin
  WriteBuffer(Value, SizeOf(integer));
end;

procedure TFileStreamEx.WriteString(const Value: string);
var
  N: integer;
begin
  N := Length(Value) * SizeOf(Char);
  WriteInteger(N);
  if N > 0 then
    WriteBuffer(Value[1], N);
end;

end.
  Mit Zitat antworten Zitat
 


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:59 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz