![]() |
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 |
Re: Monatskürzel "Jan".."Dec" in 01..12
Kuck dir mal DecodeDate und EncodeDate an.
|
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! |
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:
Man liest sich, Stanlay :hi:
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; |
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...
|
Re: Monatskürzel "Jan".."Dec" in 01..12
Guck mal nach FormatDateTime ^^
mfG mirage228 |
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? ;)
|
Re: Monatskürzel "Jan".."Dec" in 01..12
case mit strings?
Geht nur indirekt, und ist nicht schnell... |
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. |
Re: Monatskürzel "Jan".."Dec" in 01..12
Vorschlag für diesen und ähnliche Fälle: (TotalEdit nach 2xNachdenken)
Delphi-Quellcode:
Gruß
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; |
Re: Monatskürzel "Jan".."Dec" in 01..12
Delphi-Quellcode:
Gruß Hagen
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; |
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:
sondern bei großen Arrays ggf schneller, weil
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;
Delphi-Quellcode:
lediglich Result gegen null testet, wohingegen ggf (sofern zB nicht mit const gearbeitet wird, wie von Leuselator gezeigt)
Result >= Low(AnArray)
Delphi-Quellcode:
jedesmal einen Speicherzugriff verursacht...
Result <= High(AnArray)
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; |
Re: Monatskürzel "Jan".."Dec" in 01..12
BTW, in der Unit StrUtils gibt es bereits die beiden Funktionen AnsiMatchStr und AnsiMatchStr:
Zitat:
|
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:
Gruß Hagen
var
I: Integer; begin for I := Low() to High() do if Data[I] = XYZ then begin Result := I; Exit; end; end; |
Re: Monatskürzel "Jan".."Dec" in 01..12
Hallo Hagen,
im Vordergrund stand bei meiner Antwort die Übersichtlichkeit des Quellcodes Zitat:
Zitat:
Delphi-Quellcode:
übersichtlicher als
function MyProc: Integer;
begin Result:= 0; while SomeCriteria do Inc(Result); end;
Delphi-Quellcode:
function MyProc: Integer;
var myExtension: Integer; begin myExtension:= 0; while SomeCriteria do Inc(myExtension); Result:= myExtension; end; Zitat:
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:
innerhalb der For-Schleife und dagegen die errechnung des Indexes innerhalb der Whileschleife:
[b]DoSthWithStr(AnArray[myIndex])[/b]
mov EAX, [EBX] call DoSthWithStr add EBX, $04
Code:
[b]DoSthWithStr(AnArray[myIndex])[/b]
mov EAX, [EBP-$04] mov EAX, [EAX+EBX*4] call DoSthWithStr inc EBX 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... |
Re: Monatskürzel "Jan".."Dec" in 01..12
Zitat:
Zitat:
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 |
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ß |
Re: Monatskürzel "Jan".."Dec" in 01..12
Zitat:
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:
Formal:
Code:
und damit ist die Anzahl der Iterationen nicht bekannt.
x=p v x<=p <=> x<=p != x=p
Zitat:
|
Re: Monatskürzel "Jan".."Dec" in 01..12
Hallo Leuselator,
Zitat:
Zitat:
Zitat:
|
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. |
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; |
Re: Monatskürzel "Jan".."Dec" in 01..12
Delphi-Quellcode:
sag ich ma.
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; |
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:
so dass der Client (Aufrufer Deiner Routine) nicht zwischen einem ungültigen Kürzel und dem Januar unterscheiden kann.
monthbystr('jan')=monthbystr('wrong')
|
Re: Monatskürzel "Jan".."Dec" in 01..12
Delphi-Quellcode:
und es is immer noch kurz
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; |
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; |
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:
Delphi-Quellcode:
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...
monthbystr('Jan')=monthbystr('Jan F')
|
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; |
Re: Monatskürzel "Jan".."Dec" in 01..12
ausserdem... wo gibts denn da probleme bei der Performance? das ist doch nicht nennenswert. oder ?
|
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:
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.
monthbystr('n f')=monthbystr('jan')
|
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; |
Re: Monatskürzel "Jan".."Dec" in 01..12
Zitat:
|
Re: Monatskürzel "Jan".."Dec" in 01..12
Zitat:
Gruß Hagen |
Re: Monatskürzel "Jan".."Dec" in 01..12
okokok. is ja gut. gute lösung. hab sie vorher beim überfliegen nich gesehn 8)
|
Re: Monatskürzel "Jan".."Dec" in 01..12
Hallo hboy,
Zitat:
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... |
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?
|
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:
|
Re: Monatskürzel "Jan".."Dec" in 01..12
Zitat:
|
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