AGB  ·  Datenschutz  ·  Impressum  







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

Slicing for Delphi™

Ein Thema von Meflin · begonnen am 24. Mär 2009 · letzter Beitrag vom 22. Apr 2009
Antwort Antwort
Seite 1 von 3  1 23      
Benutzerbild von Meflin
Meflin

Registriert seit: 21. Aug 2003
4.856 Beiträge
 
#1

Slicing for Delphi™

  Alt 24. Mär 2009, 18:05
Moin moin!

Der eine oder andere von euch kennt sicher aus anderen Programmiersprachen das Slicing-Konzept. Für die, die es nicht kennen, hier eine kurze Einführung:

Dass man auf ein Listenelement mittels Liste[Index] zugreifen kann, ist sicher nichts neues. Das dumme daran: Man bekommt immer nur ein Element zurück. Und hier kommt das Slicing ins Spiel, welches derartige Zugriffe quasi exponentiell nützlicher macht.

Die Grundlegende Syntax ist Liste[StartIndex:StopIndex]. Und eigentlich ist das schon ziemlich selbsterklärend, hier ein paar Beipsiele, was man damit so machen kann:
Code:
Liste[0:4]   0tes - 5tes Element
Liste[3:4]   4tes - 5tes Element
Liste[:5]    0tes - 6tes Element
Liste[3:]    4tes - letztes Element
Liste[1:-1]  zweites - vorletztes Element

u.v.m.
Nun, wems bis jetzt noch nicht gedämmert ist: Soetwas gibt es in Delphi leider nicht

Ich bin grade dabei mir zu überlgen, inwieweit man das in Delphi integrieren könnte. Herausgekommen ist dabei bis jetzt eine Beispielimplementation TSlicedStringList:
Delphi-Quellcode:
unit SlicedStringList;

interface

uses
  Classes;

type
  TSlicedStringList = class(TStringList)
  private
    function GetStrings(Slice: string): TStrings;
    //procedure SetStrings(Slice: string; const Value: TStrings);
  public
    property Strings[Index: Integer]: string read Get write Put; default;
    property Strings[Slice: string]: TStrings read GetStrings; default;
  end;

implementation

uses
  SysUtils, Dialogs;

{ TExtStringList }
type
  TIntArray = array of Integer;

function GetIntArrayFromSlice(const Slice: string; const Max: Integer): TIntArray;
var
  strStartPos, strStopPos: string;
  StartPos, StopPos, i: Integer;
begin
  strStartPos := Copy(Slice, 1, Pos(':', Slice) - 1);
  strStopPos := Copy(Slice, Pos(':', Slice) + 1, Length(Slice));

  case Length(strStartPos) of
    0: StartPos := 0;
    else StartPos := StrToInt(strStartPos);
  end;

  case Length(strStopPos) of
    0: StopPos := Max;
    else StopPos := StrToInt(strStopPos);
  end;

  if StartPos < 0 then StartPos := Max + StartPos;
  if StopPos < 0 then StopPos := Max + StopPos;

  SetLength(Result, StopPos - StartPos + 1);
  for i := StartPos to StopPos do begin
    Result[i - StartPos] := i;
  end;
end;

function TSlicedStringList.GetStrings(Slice: string): TStrings;
var
  i: Integer;
begin
  Result := TStringList.Create;
  case Pos(':', Slice) of
    0: Result.Add(Strings[StrToInt(Slice)]);
    else begin
      for i in GetIntArrayFromSlice(Slice, Count - 1) do
        Result.Add(Strings[i]);
    end;
  end;
end;

//procedure TSlicedStringList.SetStrings(Slice: string; const Value: TStrings);
//begin
//
//end;

end.
Das neue an ihr: sowas geht
lst := StringList['1:4']; Im Anhang findet ihr eine kleine Demo-Anwendung dazu, nix großes, soll nur das Prinzip verdeutlichen und enthält KEINE Fehlerabfragen, derartige 'Bugreports' sind also überflüssig




Die spannende Frage ist nun:
Was haltet ihr davon? Nützlich? Fürn Popo? Unbedingt weiterentwicklen?

Und wenn weiterentwickeln, was wären die Konventionen, die ihr bevorzugegen würdet?
Soll [-1] Das letzte oder das vorletzte Element liefern? (Beides ergibt Sinn).
Soll der EndIndex im Ergebnis enthalten sein oder nicht (beide Versionen gibt es in anderen Sprachen).

Fällt euch eine bessere Möglichkeit ein, als das ganze per string zu übergeben (was nicht sehr nützlich ist, aber es ist der einizge Weg, der mir spontan eingefallen ist)?


Nuja, her mit euren Ideen und Anregungen
Miniaturansicht angehängter Grafiken
minidemo_299.jpg  
Angehängte Dateien
Dateityp: exe slicing_126.exe (442,5 KB, 11x aufgerufen)
  Mit Zitat antworten Zitat
Namenloser

Registriert seit: 7. Jun 2006
Ort: Karlsruhe
3.724 Beiträge
 
FreePascal / Lazarus
 
#2

Re: Slicing for Delphi™

  Alt 24. Mär 2009, 18:13
Zitat von Meflin:
Fällt euch eine bessere Möglichkeit ein, als das ganze per string zu übergeben (was nicht sehr nützlich ist, aber es ist der einizge Weg, der mir spontan eingefallen ist)?
Ich würde es so machen, wie bei TCanvas.Pixels:
Delphi-Quellcode:
TSlicedStringList = class
private
  function GetSlice(From, To: integer): TStrings;
  ...

public
  property Slices[From,To: integer]: TStrings read GetSlice;
  ...

end;

...
Delphi-Quellcode:
lst := SlicedStringList.Slices[1,4];
lst.free;
  Mit Zitat antworten Zitat
Benutzerbild von Meflin
Meflin

Registriert seit: 21. Aug 2003
4.856 Beiträge
 
#3

Re: Slicing for Delphi™

  Alt 24. Mär 2009, 18:25
Zitat von NamenLozer:
Ich würde es so machen, wie bei TCanvas.Pixels
Habe ich auch drüber nachgedacht, der Nachteil daran ist, dass das spaßige von-rechts-Zählen quasi komplett wegfällt, weil man immer zwei Parameter angeben muss.
[-1] Wäre das letzte Element, [0, -1] würde was anderes bedeuten, man müsste dafür also [-1, -1] übergeben.

Auch irgendwie blöd
  Mit Zitat antworten Zitat
mr_emre_d
(Gast)

n/a Beiträge
 
#4

Re: Slicing for Delphi™

  Alt 24. Mär 2009, 18:35
Zitat von Meflin:
Zitat von NamenLozer:
Ich würde es so machen, wie bei TCanvas.Pixels
Habe ich auch drüber nachgedacht, der Nachteil daran ist, dass das spaßige von-rechts-Zählen quasi komplett wegfällt, weil man immer zwei Parameter angeben muss.
[-1] Wäre das letzte Element, [0, -1] würde was anderes bedeuten, man müsste dafür also [-1, -1] übergeben.

Auch irgendwie blöd
Ich habe heir mal eine kleine rekursive Function gepostet, mit der man einen Wert in einem Wertebereich, die man angibt, zurückbekommt !

EDIT:
http://www.delphipraxis.net/internal...929&highlight=
Siehe mein Beitrag

MfG
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#5

Re: Slicing for Delphi™

  Alt 24. Mär 2009, 18:46
Interessant!
Ich würde das mit dem Dekorator Design-Pattern lösen.
Dazu leitet man von TStrings ab und muss dann natürlich alle virtuellen (und abstrakten) Methoden überschreiben.
Dabei leitet man die Methoden nur auf das TStrings-Objekt weiter, dass im Konstruktor übergeben wurde.
Delphi-Quellcode:
TSlicedStrings = class(TStrings)
private
   FStrings : TStrings;
   function GetSlice(const Range: string): TStrings;
   //procedure SetStrings(Slice: string; const Value: TStrings);
public
   constructor Create(AStrings:TStrings);
   function Add(const S: string): Integer; override;

   property Slice[const Range: string]: TStrings read GetStrings;
   property Slice[fromIdx,toIdx:Integer]:TStrings; // 2. Variante
end;
constructor TSlicedStrings.Create(AStrings:TStrings);
begin
  inherited Create;
  FStrings := AStrings;
end;
function TSlicedStrings.Add(const S: string): Integer; override;
begin
  Result := FStrings.Add(S); // einfach auf internes Objekt umleiten
end;


function TSlicedStrings.GetSlice(const Range: string): TStrings;
var
  i,j : Integer;
begin
  Result := TStringList.Create;
  case Pos(':', Range) of
    0:
    begin
      j := StrToInt(Range);
       Result.AddObject(Strings[j], Objects[j]);
    end
    else begin
      for i in GetIntArrayFromSlice(Range, Count - 1) do
        Result.AddObject(Strings[i], Objects[i]);
    end;
  end;
end;
Andreas
  Mit Zitat antworten Zitat
Dax
(Gast)

n/a Beiträge
 
#6

Re: Slicing for Delphi™

  Alt 24. Mär 2009, 18:50
Zitat von Meflin:
[-1] Wäre das letzte Element, [0, -1] würde was anderes bedeuten, man müsste dafür also [-1, -1] übergeben.

Auch irgendwie blöd
Du könntest zwei Properties einbauen, einmal mit einem Parameter, einmal mit zwei. Ob man beide defaulten kann, weiß ich gerade nicht - aber schöner als Strings zu verwenden wäre es allemal.
  Mit Zitat antworten Zitat
alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#7

Re: Slicing for Delphi™

  Alt 24. Mär 2009, 19:50
Lustig. Der Nachteil des String-Parametersi ist die etwas sehr umständliche Verwurstung von Variablen. I.A. benötige ich nicht das 2. bis 5. Element, sondern das i.te bis j.te (bzw. N Elemente ab Position I). Ich müsste mir also den Deskriptorstring mittels IntToStr oder Format zusammenbasteln. Das ist irgendwie blöd.

MySlicedStringList := StringList[Format('%d:%d',[I,N])]; Übersichlich geht anders.
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat
Benutzerbild von Meflin
Meflin

Registriert seit: 21. Aug 2003
4.856 Beiträge
 
#8

Re: Slicing for Delphi™

  Alt 24. Mär 2009, 20:04
Zitat von alzaimar:
Der Nachteil des String-Parametersi ist die etwas sehr umständliche Verwurstung von Variablen ... Übersichlich geht anders.
Da hast du völlig Recht und das ist mir auch bewusst. Nur wenn man beim "originalen" Slicing bleibt, dann ist ja [:-1] etwas anderes als [-1] (nämlich einmal die komplette Liste und einmal das letzte Element). Die Dynamik geht irgendwie verloren, wenn man mehrere properties implementiert Auch gibt es ja noch erweiterte Slicing-Techniken, [1::2] wäre jedes zweite Element, oder [1::3] jedes dritte beginnend mit dem zweiten. Ich weiß nicht ob ich sowas überhaupt implementieren will. Aber da endet dann der Umgang mit blosen Integern.

Zitat von Dax:
Du könntest zwei Properties einbauen, einmal mit einem Parameter, einmal mit zwei. Ob man beide defaulten kann, weiß ich gerade nicht
Das sollte möglich sein.

Zitat von shmia:
Ich würde das mit dem Dekorator Design-Pattern lösen.
Dazu leitet man von TStrings ab und muss dann natürlich alle virtuellen (und abstrakten) Methoden überschreiben.
Dabei leitet man die Methoden nur auf das TStrings-Objekt weiter, dass im Konstruktor übergeben wurde.
Danke, das ist ein interessanter Ansatz

Zitat von mr_emre_d:
Ich habe heir mal eine kleine rekursive Function gepostet, mit der man einen Wert in einem Wertebereich, die man angibt, zurückbekommt !
Hm. Welches Problem meintest du soll die Lösen ?
  Mit Zitat antworten Zitat
mr_emre_d
(Gast)

n/a Beiträge
 
#9

Re: Slicing for Delphi™

  Alt 24. Mär 2009, 21:17
xD
Um etwas klarzustellen -> meinst du mit [0:-1] ~ [0:Anzahl der Rechten Elemente - 1] ?

Falls nein, dann war mal mein Beitrag wieder voll daneben

MfG
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#10

Re: Slicing for Delphi™

  Alt 24. Mär 2009, 22:46
bei Arrays kann man auch Copy nutzen ... ok, ohne das "von rechts"
Delphi-Quellcode:
var a: Array of Double;

a := Copy(a, 5, 9);
ansonsten gibt's 2 Möglichkeiten für die Parameter:
Delphi-Quellcode:
public
  property Slices[From: Integer; To: Integer = MinInt]: TStrings read GetSlice;

// if To = MinInt then {to=from}
// else {from,to}
Delphi-Quellcode:
public
  property Slices[From, To: Integer]: TStrings read GetSlice2; Default;
  property Slices[To: Integer]: TStrings read GetSlice1; Default;
  ...
$2B or not $2B
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


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 00:14 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz