Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Monatskürzel "Jan".."Dec" in 01..12 umwandeln (https://www.delphipraxis.net/15437-monatskuerzel-jan-dec-01-12-umwandeln.html)

Steffen 28. Jan 2004 19:08


Monatskürzel "Jan".."Dec" in 01..12 umw
 
Hallo!

Ich habe folgende Strings gegeben:
'Jan', 'Feb', 'Mar', 'Apr', 'May' .. 'Dec'

gibt es eine Funktion diese in ihre Nummern umzuwandeln, oder muss ich das selber schreiben?



Noch besser Wäre 'ne Funktion die mir ein Datum wie "08 Oct 2003" in TDateTime umwandelt...
(Ich habe mit StrToDate(..) nur folgendes Format umwandeln können '08.10.2003')

Vielen Dank im Voraus!
Steffen

Luckie 28. Jan 2004 19:09

Re: Monatskürzel "Jan".."Dec" in 01..12
 
Kuck dir mal DecodeDate und EncodeDate an.

Steffen 28. Jan 2004 19:14

Re: Monatskürzel "Jan".."Dec" in 01..12
 
...die bringen mich auch nur weiter, wenn die Werte schon Zahlen sind!
Ich habe Strigs als Quelle!

Stanlay Hanks 28. Jan 2004 19:15

Re: Monatskürzel "Jan".."Dec" in 01..12
 
Oder einfach (was heißt einfach, eigentlich zu umständlich), aber der Vollständigkeit halber:

Delphi-Quellcode:
function TForm1.MonthToNumber(Str: String): Integer;
begin
  IF Str = 'Jan' THEN result := 1 ELSE
  IF Str = 'Feb' THEN result := 2 ELSE
  IF Str = 'Mar' THEN result := 3 ELSE
  IF Str = 'Apr' THEN result := 4 ELSE
  IF Str = 'May' THEN result := 5 ELSE
  IF Str = 'Jun' THEN result := 6 ELSE
  IF Str = 'Jul' THEN result := 7 ELSE
  IF Str = 'Aug' THEN result := 8 ELSE
  IF Str = 'Sep' THEN result := 9 ELSE
  IF Str = 'Oct' THEN result := 10 ELSE
  IF Str = 'Nov' THEN result := 11 ELSE
  IF Str = 'Dec' THEN result := 12
end;
Man liest sich, Stanlay :hi:

Steffen 28. Jan 2004 19:16

Re: Monatskürzel "Jan".."Dec" in 01..12
 
das das ganze mit 12 IF-THEN Konstrukten geht ist klar, aber das wollte ich eigentlich vermeiden...

mirage228 28. Jan 2004 19:31

Re: Monatskürzel "Jan".."Dec" in 01..12
 
Guck mal nach FormatDateTime ^^

mfG
mirage228

n00b_on_knees 28. Jan 2004 19:35

Re: Monatskürzel "Jan".."Dec" in 01..12
 
eventuell statt if, case? wäre hier denke ich schon besser..aber ich denke das ist dir auch klar? ;)

Steffen 28. Jan 2004 19:38

Re: Monatskürzel "Jan".."Dec" in 01..12
 
case mit strings?
Geht nur indirekt, und ist nicht schnell...

choose 29. Jan 2004 00:28

Re: Monatskürzel "Jan".."Dec" in 01..12
 
Hallo Steffen,

in der Unit SysUtils existieren die globalen Variablen ShortMonthNames, LongMonthNames, ShortDayNames und LongDayNames. In ihnen werden im landesspezifischen Format die entsprechenden Daten zur Verfügung gestellt.

Leuselator 29. Jan 2004 01:27

Re: Monatskürzel "Jan".."Dec" in 01..12
 
Vorschlag für diesen und ähnliche Fälle: (TotalEdit nach 2xNachdenken)
Delphi-Quellcode:
function IndexOfArrayItem(TheArray : Array of String ;Item : String ):Integer; overload;
function IndexOfArrayItem(TheArray : Array of Byte   ;Item : Byte   ):Integer; overload;
function IndexOfArrayItem(TheArray : Array of Integer ;Item : Integer ):Integer; overload;
function IndexOfArrayItem(TheArray : Array of Char   ;Item : Char   ):Integer; overload;
function IndexOfArrayItem(TheArray : Array of Currency;Item : Currency):Integer; overload;
function IndexOfArrayItem(TheArray : Array of Double ;Item : Double ):Integer; overload;

// diese Funktion benutzt eine der oben deklarierten:
function EnglishMonthToInt(Month : String):Integer;

implementation

function IndexOfArrayItem(TheArray : Array of String;Item : String):Integer;
begin
  Result := Low(TheArray);
  while (Result <= High(TheArray))
    and (TheArray[Result] <> Item)
    do Inc(Result);
  if Result > High(TheArray)
    then Result := -1;
end;

function IndexOfArrayItem(TheArray : Array of Byte;Item : Byte):Integer;
begin
  Result := Low(TheArray);
  while (Result <= High(TheArray))
    and (TheArray[Result] <> Item)
    do Inc(Result);
  if Result > High(TheArray)
    then Result := -1;
end;

function IndexOfArrayItem(TheArray : Array of Integer;Item : Integer):Integer;
begin
  Result := Low(TheArray);
  while (Result <= High(TheArray))
    and (TheArray[Result] <> Item)
    do Inc(Result);
  if Result > High(TheArray)
    then Result := -1;
end;

function IndexOfArrayItem(TheArray : Array of Char;Item : Char):Integer;
begin
  Result := Low(TheArray);
  while (Result <= High(TheArray))
    and (TheArray[Result] <> Item)
    do Inc(Result);
  if Result > High(TheArray)
    then Result := -1;
end;

function IndexOfArrayItem(TheArray : Array of Currency;Item : Currency):Integer;
begin
  Result := Low(TheArray);
  while (Result <= High(TheArray))
    and (TheArray[Result] <> Item)
    do Inc(Result);
  if Result > High(TheArray)
    then Result := -1;
end;

function IndexOfArrayItem(TheArray : Array of Double;Item : Double):Integer;
begin
  Result := Low(TheArray);
  while (Result <= High(TheArray))
    and (TheArray[Result] <> Item)
    do Inc(Result);
  if Result > High(TheArray)
    then Result := -1;
end;

function EnglishMonthToInt(Month : String):Integer;
const
  MonthArray : Array[1..12] of String
              = ('JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG','SEP','OCT','NOV','DEC');
begin
  Result IndexOfArrayItem(MonthArray,Month);
end;
Gruß

negaH 29. Jan 2004 03:29

Re: Monatskürzel "Jan".."Dec" in 01..12
 
Delphi-Quellcode:
function IndexOfMonth(const Name: String): Integer;
begin
  Result := Pos('.' + AnsiUpperCase(Name) + '.', '.JAN.FEB.MAR.APR.MAY.JUN.JUL.AUG.SEP.OCT.NOV.DEC.');
  if Result > 0 then Result := (Result -1) div 4 +1;
end;
Gruß Hagen

choose 29. Jan 2004 09:32

Re: Monatskürzel "Jan".."Dec" in 01..12
 
Hallo Leuselator hallo Steffen,

falls ihr Euch für eine Variante mit case entscheiden solltest, wäre es von Vorteil, wenn Ihr in Euren Schleifen von oben nach unten iteriert. Es wird so nicht nur etwas übersichtlicher
Delphi-Quellcode:
function IndexOfArrayItem(const AnArray : array of string;
  const AnItem : string):Integer;
begin
  Result := High(TheArray);
  while (Result >= Low(AnArray)) and (AnArray[Result] <> AnItem)
    do Dec(Result);
end;
sondern bei großen Arrays ggf schneller, weil
Delphi-Quellcode:
Result >= Low(AnArray)
lediglich Result gegen null testet, wohingegen ggf (sofern zB nicht mit const gearbeitet wird, wie von Leuselator gezeigt)
Delphi-Quellcode:
Result <= High(AnArray)
jedesmal einen Speicherzugriff verursacht...

Wenn ich das ich richtig sehe, Steffen, besitzt Du D7E. Dort sollte es eine überladene Variante von StrToDate geben, die mit eigenen Format-Einstellungen arbeiten kann. Für eine solche Verwendung könntest Du Dir mit GetLocaleFormatSettings die entsprechenden US-Einstellungen in einer Variablen halten und Deine Umformung, durch eine Funktion gewrappt wie folgt gestalten:
Delphi-Quellcode:
function MyStringToDate(const AString: string): TDate;
begin
  Result:= StringToDate(AString, MyStoredSettings);
end;

choose 29. Jan 2004 09:47

Re: Monatskürzel "Jan".."Dec" in 01..12
 
BTW, in der Unit StrUtils gibt es bereits die beiden Funktionen AnsiMatchStr und AnsiMatchStr:
Zitat:

Zitat von OH
Mit ~ können Sie ermitteln, ob der String AText im Array AValues enthalten ist [und dessen Index ermitteln]


negaH 30. Jan 2004 06:41

Re: Monatskürzel "Jan".."Dec" in 01..12
 
@choose, deine Annahme das das Runterzählen schneller ist ist einfach falsch.

1.) Da du Result als Zählervariable benutzt verhinderst du das der Compiler den Code besser optimieren kann
2.) WENN der Compiler optimieren kann dann würde er schnelleren Code mit einer simplen for to Schleife erzeugen. In diesem Beispiel würde er Assemblercode erzeugen der auch gegen Null überprüft
3.) Eine BottomUp Schleife ist Cache-unfreundlich

besser ist folgender Code
Delphi-Quellcode:
var
  I: Integer;
begin
  for I := Low() to High() do
    if Data[I] = XYZ then
    begin
      Result := I;
      Exit;
    end;
end;
Gruß Hagen

choose 30. Jan 2004 09:41

Re: Monatskürzel "Jan".."Dec" in 01..12
 
Hallo Hagen,

im Vordergrund stand bei meiner Antwort die Übersichtlichkeit des Quellcodes
Zitat:

Es wird so nicht nur etwas übersichtlicher, sondern ggf auch etwas schneller
ich wollte somit keinesfalls "die performanteste Lösung" aufzeigen, sondern einen brauchbaren Kompromiss.
Zitat:

Zitat von negaH
Da du Result als Zählervariable benutzt verhinderst du das der Compiler den Code besser optimieren kann

Das stimmt und dient der Übersichtlichkeit. Es ist wahr, dass auch die Speicherung von Zwischenwerten in Result als umstritten gilt, ich persönlich finde jedoch ein Kontrukt der Art
Delphi-Quellcode:
function MyProc: Integer;
begin
  Result:= 0;
  while SomeCriteria do
    Inc(Result);
end;
übersichtlicher als
Delphi-Quellcode:
function MyProc: Integer;
var
  myExtension: Integer;
begin
  myExtension:= 0;
  while SomeCriteria do
    Inc(myExtension);
  Result:= myExtension;
end;
Zitat:

Zitat von negaH
der Compiler [..] würde [..] schnelleren Code mit einer simplen for to Schleife erzeugen.

Das stimmt, auch hier wirkt eine Lösung mit Exit oder Break eher als Kunstgriff und dient als Hauptzweck der Performancesteigerung. Ich möchte keine Diskussion über Ästhetik anzetteln, aber nach der Klassischen Auffassung sollten For-Schleifen genau dann eingesetzt werden, wenn die Anzahl der Iterationen bekannt ist, was hier nicht der Fall ist. Break und Exit eignen sich häufig in komplexeren Fällen, um Kontrollstrukturen zu verlassen, die Abbruchbedingung dieser Schleife hingegen lässt sich "sauber" definieren, so dass die Veränderung der Ablaufsteuerung ausschließlich der Performancesteigerung dient.
Tatsächlich ist die For-Schleife nicht nur bei der Abbruchbedingung genauso performant wie die TopDown lösung, sich arbeitet sogar direkt mit einem Index im array, so dass die Errechnung selbigens bei der While-Schleife entfält.
Code:
[b]DoSthWithStr(AnArray[myIndex])[/b]
  mov EAX, [EBX]
  call DoSthWithStr
  add EBX, $04
innerhalb der For-Schleife und dagegen die errechnung des Indexes innerhalb der Whileschleife:
Code:
[b]DoSthWithStr(AnArray[myIndex])[/b]
  mov EAX, [EBP-$04]
  mov EAX, [EAX+EBX*4]
  call DoSthWithStr
  inc EBX
Zitat:

Zitat von negaH
Eine BottomUp Schleife ist Cache-unfreundlich

Ich simmte Dir iA zu, allerdings arbeiten wir hier mit Strings, die idR wahllos auf dem Heap platziert sind, so dass bei der Verarbeitung der Strings ohnehin ungeordnet Speicherzugriffe stattfinden. Lediglich die Referenzen nicht aber der im Verhätnis zu ihnen große Speicherbereich zur tatsächlichen Verarbeitung (vergleichen, verlängern, kürzen, etc) könnte somit cache-freundlich Bearbeitet werden.


Für performancekritische Lösungen des ursprünglichen Problems von Steffen würde ich ebenfalls eine Lösung der von Dir vorgeschlagenen Art verwenden, jedoch mit einem besseren Match-Algorithmus als der in Pos implementierte, bspw einer modifizierte Version des Boyer-Moore-Algorithmus oder einer Form des Hashings...

negaH 30. Jan 2004 09:57

Re: Monatskürzel "Jan".."Dec" in 01..12
 
Zitat:

Für performancekritische Lösungen des ursprünglichen Problems von Steffen würde ich ebenfalls eine Lösung der von Dir vorgeschlagenen Art verwenden, jedoch mit einem besseren Match-Algorithmus als der in Pos implementierte, bspw einer modifizierte Version des Boyer-Moore-Algorithmus oder einer Form des Hashings...
Wie ? um mal eben 12 Monatsnamen in eine Zahl umzuwandeln ? Alleine der Overhead um den Boyer-More zu initialisieren dauert länger als eine Pos() Funktion die sequentiell in 49 Bytes sucht.

Zitat:

..wenn die Anzahl der Iterationen bekannt ist, was hier nicht der Fall ist..
Wieso ? Es sind exakt 12 Iteration maximal. Damit ist es also auch sinnvoll eine for I := 1 to 12 Schleife zu benutzen und bei Übereinstimmung abzubrechen.

Ich verstehe deine Motive saubern Code zu produzieren sehr gut, bin ja selber ein Pedant :), ABER ich kann dir nicht zustimmen in dem Punkt das bedingte Schleifen wie while do/repeat until einfachere Schleifen sind als normale Zählschleifen.

Gruß Hagen

Leuselator 30. Jan 2004 10:32

Re: Monatskürzel "Jan".."Dec" in 01..12
 
*räusper*
Ehm - ich bin schuld :oops:!

Habe das Problem von Mücke zum Elefanten aufgeblasen, weil ich eine allgemeinere Funktion wie IndexOf bei TList für Arrays anbieten wollte. Der Code stimmt ziemlich genau mit dem der VCL zu TList.IndexOf überein. Nicht ganz klar ist mir in der losgetretenen Disskusion die Sache mit dem Prüfen gegen Null, da Low(AnArray) doch nicht zwangsläufig 0 sein muß?

Ich finde es allemal interessant, wie viele verschiedene Wege nach Rom es doch gibt - dieser Thread kann als gutes Beispiel dienen, wenn man einem Nichtprogrammierer erklären möchte, warum Softwareentwicklung immer auch stark die individuellen Denkstrukturen der beteiligten Programmierer widerspiegelt.

Also bitte nicht mehr streiten :-)
Gruß

choose 30. Jan 2004 10:36

Re: Monatskürzel "Jan".."Dec" in 01..12
 
Zitat:

Zitat von negaH
Alleine der Overhead um den Boyer-More zu initialisieren dauert länger

Für das Problem der kurzen konstanten Elemente gleicher Länge und geringer Anzahl hat Du mit Sicherheit Recht. Vielleicht doch ein Hashing, in dem konkreten Fall kann der gesamte String sogar auf ein DWord gemappt werden, so dass das Hashing eineindeutig und trivial zu errechnen ist, ohne dass die Übersichtlichkeit verloren geht (die Klammerung soll denjenigen Helfen, die sich bei der Priorität der Operatoren nicht sicher fühlen):
Delphi-Quellcode:
function IndexOfMonth(const AName: String): Integer;
const
  Hash_Jan = (Ord('J') shl 16) or (Ord('A') shl 8) or Ord('N');
  Hash_Feb = (Ord('F') shl 16) or (Ord('E') shl 8) or Ord('B');
  Hash_Mar = (Ord('M') shl 16) or (Ord('A') shl 8) or Ord('R');
  Hash_Apr = (Ord('A') shl 16) or (Ord('P') shl 8) or Ord('R');
  Hash_May = (Ord('M') shl 16) or (Ord('A') shl 8) or Ord('Y');
  Hash_Jun = (Ord('J') shl 16) or (Ord('U') shl 8) or Ord('N');
  Hash_Jul = (Ord('J') shl 16) or (Ord('U') shl 8) or Ord('L');
  Hash_Aug = (Ord('A') shl 16) or (Ord('U') shl 8) or Ord('G');
  Hash_Sep = (Ord('S') shl 16) or (Ord('E') shl 8) or Ord('P');
  Hash_Oct = (Ord('O') shl 16) or (Ord('C') shl 8) or Ord('T');
  Hash_Nov = (Ord('N') shl 16) or (Ord('O') shl 8) or Ord('V');
  Hash_Dec = (Ord('D') shl 16) or (Ord('E') shl 8) or Ord('C');

begin
  if Length(AName)<>3 then
    Result:= 0
  else
    case (Ord(UpCase(AName[1])) shl 16) or
         (Ord(UpCase(AName[2])) shl 8 ) or
          Ord(UpCase(AName[3])) of
      Hash_Jan: Result:= 1;
      Hash_Feb: Result:= 2;
      Hash_Mar: Result:= 3;
      Hash_Apr: Result:= 4;
      Hash_May: Result:= 5;
      Hash_Jun: Result:= 6;
      Hash_Jul: Result:= 7;
      Hash_Aug: Result:= 8;
      Hash_Sep: Result:= 9;
      Hash_Oct: Result:= 10;
      Hash_Nov: Result:= 11;
      Hash_Dec: Result:= 12;
    else
      Result:= 0;
  end;
end;
Zitat:

Zitat von negaH
Wieso [die anzahl der Iterationen ist doch bekannt]? Es sind exakt 12 Iteration maximal.

:) Die Formulierungen "exakt p" und "genau p" sind nach meinem (mathematischen) Empfinden synonym zu "p und nur p" zu verwenden und sind nicht äquivalent zu "p oder maximal p". Um genau zu sein, entspricht die Aussage "p oder maximal p" der Aussage "maximal p"
Formal:
Code:
 x=p v x<=p <=> x<=p != x=p
und damit ist die Anzahl der Iterationen nicht bekannt.

Zitat:

Zitat von negaH
ich kann dir nicht zustimmen [..] das bedingte Schleifen [..] einfachere Schleifen sind als [..] Zählschleifen.

Das habe ich auch nicht behauptet. In Deinem Fall allerdings verwendest Du zu eine Schleife mit einer nach Definition genauen Anzahl von Iterationen mit einer zusätzlichen Fallunterscheidung und einem Konstrukt, dass noch nicht einmal in jeder Programmiersprache vorgesehen ist, dazu, etwas zu tun, wofür eine andere Schleifenform definiert worden ist, nämlich dem Iterieren bis eine bei jeder Iteration zu berechnenen Abbruchbedingung erfüllt ist.

choose 30. Jan 2004 10:41

Re: Monatskürzel "Jan".."Dec" in 01..12
 
Hallo Leuselator,
Zitat:

Zitat von Leuselator
Nicht ganz klar ist mir [..] die Sache mit dem Prüfen gegen Null, da Low(AnArray) doch nicht zwangsläufig 0 sein muß?

es handelt sich um einen offenen Array-Parameter zu der in der OH folgendes zu lesen ist:
Zitat:

Zitat von OH
Sie sind stets nullbasiert. Das erste Element trägt immer die Indexnummer 0, das zweite die 1 usw. Die Standardfunktionen Low und High geben 0 bzw. Length - 1 zurück. Die Funktion SizeOf gibt die Größe des Arrays zurück, das an die Routine übergeben wird.

Zitat:

Zitat von Leuselator
Also bitte nicht mehr streiten

Ich empfinde die Beiträge eher als ansprechende Diskussion (nein, das ist nicht euphemistisch gefärbt) und freue mich immer zu neuen Ansätzen angeregt zu werden :)

Steffen 2. Feb 2004 14:04

Re: Monatskürzel "Jan".."Dec" in 01..12
 
Danke für die Zahlreichen Antworten...!

Nun weiß ich aber nicht, welcher Lösungsansatz nun wirklich der einfachste, beste und schnellste weg zur Lösung ist.

Leuselator 2. Feb 2004 14:10

Re: Monatskürzel "Jan".."Dec" in 01..12
 
Bei mir sieht es nun so aus (dank der Anregungen aus diesem Thread!):
Delphi-Quellcode:
type
  TLsLand = (GER,USA,GBT);

function IndexOfArrayItem(TheArray : Array of String ;Item : String ):Integer; overload;
function IndexOfArrayItem(TheArray : Array of Byte   ;Item : Byte   ):Integer; overload;
function IndexOfArrayItem(TheArray : Array of Integer ;Item : Integer ):Integer; overload;
function IndexOfArrayItem(TheArray : Array of Char   ;Item : Char   ):Integer; overload;
function IndexOfArrayItem(TheArray : Array of Currency;Item : Currency):Integer; overload;
function IndexOfArrayItem(TheArray : Array of Double ;Item : Double ):Integer; overload;
function IndexOfArrayItem(TheArray : Array of Boolean ;Item : Boolean ):Integer; overload;

function ShortMonStrToInt(Month : String; Land : TLsLand):Integer;
function LongMonStrToInt(Month : String; Land : TLsLand):Integer;

implementation

function IndexOfArrayItem(TheArray : Array of String;Item : String):Integer;
begin
  Result := High(TheArray);
  while (Result >= 0) and (TheArray[Result] <> Item) do Dec(Result);
end;
// usw. usf. für alle überladenen Versionen bis:
function IndexOfArrayItem(TheArray : Array of Boolean;Item : Boolean):Integer;
begin
  Result := High(TheArray);
  while (Result >= 0) and (TheArray[Result] <> Item) do Dec(Result);
end;

function ShortMonStrToInt(Month : String; Land : TLsLand):Integer;
const
  EngArray : Array[0..11] of String
              = ('JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG','SEP','OCT','NOV','DEC');
  GerArray1 : Array[0..11] of String
              = ('JAN','FEB','MRZ','APR','MAI','JUN','JUL','AUG','SEP','OKT','NOV','DEZ');
  GerArray2 : Array[0..11] of String
              = ('JAN','FEB','MÄR','APR','MAI','JUN','JUL','AUG','SEP','OKT','NOV','DEZ');
begin
  case Land of
  USA,GBT : Result := IndexOfArrayItem(EngArray,AnsiUpperCase(Month));
  GER    : begin
              Result := IndexOfArrayItem(GerArray1,AnsiUpperCase(Month));
              if Result < 0 then Result := IndexOfArrayItem(GerArray2,AnsiUpperCase(Month));
            end;
  else raise Exception.Create('Nichtdefiniertes Land übergeben!');
  end;
  if Result >= 0 then inc(Result); // damit man auf die Monatszahl kommt, muß um 1 erhöht werden.
end;

function LongMonStrToInt(Month : String; Land : TLsLand):Integer;
begin
  Result := ShortMonStrToInt(copy(Month,1,3), Land);
end;

hboy 2. Feb 2004 16:26

Re: Monatskürzel "Jan".."Dec" in 01..12
 
Delphi-Quellcode:
function monthbystr(s: string): integer;
const
  months = 'JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC';
begin
  result := Pos(Uppercase(s),months) shr 2;
end;
sag ich ma.

choose 2. Feb 2004 16:36

Re: Monatskürzel "Jan".."Dec" in 01..12
 
Hallo hboy,

leider hast Du bei Deiner Variante von Hagens Vorschlag (s.o.) den Fall, dass ein Kürzel keinem Monat entspricht außer Acht gelassen. Es gilt bei Deiner Lösung
Delphi-Quellcode:
monthbystr('jan')=monthbystr('wrong')
so dass der Client (Aufrufer Deiner Routine) nicht zwischen einem ungültigen Kürzel und dem Januar unterscheiden kann.

hboy 2. Feb 2004 16:42

Re: Monatskürzel "Jan".."Dec" in 01..12
 
Delphi-Quellcode:
function monthbystr(s: string): integer;
const
  months = 'JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC';
var
  position: integer;
begin
  position:= Pos(Uppercase(s),months);
  if position = -1 then
    result := -1
  else
    result := position shr 2;
end;
und es is immer noch kurz

hboy 2. Feb 2004 16:43

Re: Monatskürzel "Jan".."Dec" in 01..12
 
bzw

Delphi-Quellcode:
function monthbystr(s: string): integer;
const
  months = '   JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC';
begin
  result := Pos(Uppercase(s),months) shr 2;
end;

choose 2. Feb 2004 16:54

Re: Monatskürzel "Jan".."Dec" in 01..12
 
Hallo hboy,

ich will nicht nerven, aber erstens ergibt Deine erste Korrektur immer noch kein gültiges Ergebnis:
Zitat:

Zitat von OH
In Delphi sucht Pos in dem String S nach dem Teil-String Substr. [..] Ist Substr nicht vorhanden, wird der Wert Null zurückgegeben.

und weiterhin gilt bei Deiner zweiten Korrektur
Delphi-Quellcode:
monthbystr('Jan')=monthbystr('Jan F')
so dass weiterhin ungültige Strings auf gültige Monatsnummern gemappt werden. Ich empfand die Lösung von Hagen schon als recht gelungen und wollte mit der (zugegeben etwas längeren) Variante mit dem Hashing nur einen Vorschlag für einen performanteren Ansatz machen...

hboy 2. Feb 2004 17:04

Re: Monatskürzel "Jan".."Dec" in 01..12
 
dachte pos ist beim fehlschlag -1...
naja dann eben

Delphi-Quellcode:
function monthbystr(s: string): integer;
const months = '   JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC';
var st: string[3];
begin
  st := s[1]+s[2]+s[3];
  result := Pos(Uppercase(st),months) shr 2;
end;

hboy 2. Feb 2004 17:05

Re: Monatskürzel "Jan".."Dec" in 01..12
 
ausserdem... wo gibts denn da probleme bei der Performance? das ist doch nicht nennenswert. oder ?

choose 2. Feb 2004 17:12

Re: Monatskürzel "Jan".."Dec" in 01..12
 
Ob es ein Poblem der Performance ist, hängt vom Anwendungsfall ab. Was ich weiß ist, dass bei Deiner nunmehr dritten Korrektur folgendes gilt, hboy:
Delphi-Quellcode:
monthbystr('n f')=monthbystr('jan')
Bei der ursprünglichen Lösung von Hagen (die sehr ähnlich zu Deinem Versuch ist) findest Du einen elegenten Ansatz zu diesem Problem. Ein paar Ideen zur Performance sind ebenfalls in diesem Thread zu finden.

hboy 2. Feb 2004 17:20

Re: Monatskürzel "Jan".."Dec" in 01..12
 
dann mach doch noch


function monthbystr(s: string): integer;
const months = ' JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC';
var st: string[3]; position: integer;
begin
st := s[1]+s[2]+s[3];
position:= Pos(Uppercase(st),months);
result := position shr 2;
if position mod 4 <>0 then result :=0;
end;

ansonsten. ich habs zumindest versucht. Ausserdem liese sich dieses ord(..) shr...+ord(..) shr...+ord(..) shr... vereinfachen:

var s: string[4];
v: integer absolute s;

hboy 2. Feb 2004 17:25

Re: Monatskürzel "Jan".."Dec" in 01..12
 
Zitat:

Zitat von choose
Ob es ein Poblem der Performance ist, hängt vom Anwendungsfall ab. Was ich weiß ist, dass bei Deiner nunmehr dritten Korrektur folgendes gilt, hboy:
Delphi-Quellcode:
monthbystr('n f')=monthbystr('jan')
Bei der ursprünglichen Lösung von Hagen (die sehr ähnlich zu Deinem Versuch ist) findest Du einen elegenten Ansatz zu diesem Problem. Ein paar Ideen zur Performance sind ebenfalls in diesem Thread zu finden.

bei ihm wärs dann n.f was falsch erkannt würde

negaH 2. Feb 2004 17:34

Re: Monatskürzel "Jan".."Dec" in 01..12
 
Zitat:

bei ihm wärs dann n.f was falsch erkannt würde
Nein, dies kann nicht passieren da mein Code immer nach zB. ".JAN." oder ".OCT." sucht, d.h. die Suchworte "JAN" und "OCT" werden intern um Separatoren erweitert. In deinem Beispiel von "n.f" würde intern nach ".N.F." gesucht und eben NICHT gefunden.

Gruß Hagen

hboy 2. Feb 2004 17:48

Re: Monatskürzel "Jan".."Dec" in 01..12
 
okokok. is ja gut. gute lösung. hab sie vorher beim überfliegen nich gesehn 8)

choose 2. Feb 2004 21:33

Re: Monatskürzel "Jan".."Dec" in 01..12
 
Hallo hboy,
Zitat:

Zitat von hboy
Ausserdem liese sich dieses ord(..) shr...+ord(..) shr...+ord(..) shr... vereinfachen:

var s: string[4];
v: integer absolute s;

selbst unter der Beachtung der Ablage im Speicher (Big Endian vs Little Endian) ist dieser Verleich nicht ganz identisch, weil Du auch bei Strings der Länge 3 immer das bei einer Zuweisung undefinierte vierte Zeichen als Lowbyte des Lowwords des Ints casten würdest...
Mir ist bewusst, dass die vorgestellte Hash-Funktion optimiert werden könnte, insbesondere könnten die Aufrufe von Upcase durch ein einziges and ersetzt werdern- darum ging es aber weniger als um die Tatsache, dass auch eine eineindeutige Lösung mit der Komplexität O(1) für das Problem existiert...

Steffen 2. Feb 2004 21:35

Re: Monatskürzel "Jan".."Dec" in 01..12
 
Und wie würde die Lösung mit der Komplexität O(1) für das Problem aussehen?

choose 2. Feb 2004 21:45

Re: Monatskürzel "Jan".."Dec" in 01..12
 
Das ist die Lösung mit dem Hashing (s.o.): Für jeden Eingabestring wird eine Konstante Zeit O(1) benötigt, egal wie lang er ist oder wieviele Elemente (Monate) es gibt (sofern die Abbildung der Hash-Funktion bijektiv, also eineindeutig, ist- das ist hier der Fall).

Zitat:

Zitat von penibles Gewissen
Nun, tatsächlich (das Compilat) ist die Case-Anweisung selbst nicht ganz "konstant" in ihrer Ausführungszeit aber es entspricht dem äquivalenten Konstrukt in der Programmiersprache Pascal und ließe sich notfalls auch mit einer direkten Indizierung hinbekommen (bei zwölf Elementen wohl idR zu vernachlässigen...)


hboy 2. Feb 2004 22:29

Re: Monatskürzel "Jan".."Dec" in 01..12
 
Zitat:

Zitat von choose
Hallo hboy,
Zitat:

Zitat von hboy
Ausserdem liese sich dieses ord(..) shr...+ord(..) shr...+ord(..) shr... vereinfachen:

var s: string[4];
v: integer absolute s;

selbst unter der Beachtung der Ablage im Speicher (Big Endian vs Little Endian) ist dieser Verleich nicht ganz identisch, weil Du auch bei Strings der Länge 3 immer das bei einer Zuweisung undefinierte vierte Zeichen als Lowbyte des Lowwords des Ints casten würdest...
Mir ist bewusst, dass die vorgestellte Hash-Funktion optimiert werden könnte, insbesondere könnten die Aufrufe von Upcase durch ein einziges and ersetzt werdern- darum ging es aber weniger als um die Tatsache, dass auch eine eineindeutige Lösung mit der Komplexität O(1) für das Problem existiert...

jetzt sei mal nicht so pingelig mit einem verworfenen Ansatz. Dann machste halt noch v:= v and $00FFFFFF;


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:03 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