Delphi-PRAXiS
Seite 1 von 4  1 23     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   einen Datensatzmitgliedsnamen dynamisch zuweisen (https://www.delphipraxis.net/210966-einen-datensatzmitgliedsnamen-dynamisch-zuweisen.html)

neumimnemecky 6. Jul 2022 09:58

einen Datensatzmitgliedsnamen dynamisch zuweisen
 
(to assign a record member name dynamically)

Guten Tag,
Ich suche Hilfe, um diesen Code zu vereinfachen und die aus der INI-Datei gelesenen Werte einer Variablen vom Typ "Datensatz" zuzuweisen, wobei sich der Elementname vom Schlüsselnamen in der INI-Datei unterscheidet. Ich habe nicht herausgefunden, wie ich den Mitgliedsnamen dynamisch zuweisen kann, da es zwei Gruppen (A und B) mit denselben Schlüsselnamen in der Datei, aber unterschiedlichen Namen im Datensatz gibt.

Code:
// ini file contains pairs key_name=value , the record contains abbreviated key name
if pars[0] = 'first_frame' then k := 'first_'+group else
  if pars[0] = 'end_frame' then k := 'last_'+group else
    if pars[0] = 'first_filename' then k := 'start_name_'+group else
       if pars[0] = 'path' then
         k := 'path_'+group else
           if pars[0] = 'check_if_files_exist' then
             k := 'check_files_exist_'+group;

if group = 'A' then
 begin
   if k = 'path_A' then
     ini.basic.path_A := pars[1] else
   if k = 'first_A' then
     ini.basic.first_A := pars[1] else
   if k = 'last_A' then
     ini.basic.last_A := pars[1] else
   if k = 'start_name_A' then
     ini.basic.start_name_A := pars[1] else
   if k = 'check_files_exist_A' then
     ini.basic.check_files_exist_A := true;
 end
else if group = 'B' then
 begin
   if k = 'path_B' then
     ini.basic.path_B := pars[1] else
   if k = 'first_B' then
     ini.basic.first_B := pars[1] else
   if k = 'last_B' then
     ini.basic.last_B := pars[1] else
   if k = 'start_name_B' then
     ini.basic.start_name_B := pars[1] else
   if k = 'check_files_exist_B' then
     ini.basic.check_files_exist_B := true;
 end;
end;
(English: Good morning,
I'm looking for help to simplify this code, assigning the values read from ini file to a variable of type Record, where the member name is different from the name of the key in the ini file. I haven't figured out how can I assign the member name dynamically because there are two groups (A and B) with the same key names in the file but different names in the record.)

Deklaration:
Code:
type TBasicSettings = record
  is_scroll_vertical: boolean; scroll_type=vertical
  is_image_direction_up: boolean;
  is_search_colors_HSL: boolean;
  path_A: string;
  path_B: string;
  check_files_exist_A: boolean;
  check_files_exist_B: boolean;
  RAM_disk: string;
  RAM_free: LongWord;
  start_name_A: string;first_filename
  first_A: string;first_frame
  last_A: string;end_frame=
  start_name_B: string;first_filename
  first_B: string;first_frame
  last_B: string;end_frame
  fps: byte;
  scroll_max_shift: integer;
end;
basic.ini
[GENERAL]
Code:
[GENERAL]
scroll_type=vertical
image_direction=up
search_colors_in=HSL
H_max_difference_deg=10%
S_max_difference_per=20%
L_max_difference_per=10%
;V_max_difference_per=10%
padding_left=22
padding_right=25
padding_top=0
padding_bottom=0
detect_max_character_count_on_screen=3
arrow_1_count=2
arrow_2_count=1
arrow_3_count=1
image_1_count=1
skip_detections_on_screen_when_frame_position_is_determined=1
group_to_copy_image_data_from=A
text_copy_color_direction=BA
RAM_disk=A:
RAM_disk_free_space=1GB

peterbelow 6. Jul 2022 11:47

AW: einen Datensatzmitgliedsnamen dynamisch zuweisen
 
Nicht zu beantworten mit den gegebenen Infos. Zeig die Deklaration des Records und einen repäsentstiven Teil des Ini-Files.

neumimnemecky 6. Jul 2022 12:52

AW: einen Datensatzmitgliedsnamen dynamisch zuweisen
 
Zitat:

Zitat von peterbelow (Beitrag 1508466)
Nicht zu beantworten mit den gegebenen Infos. Zeig die Deklaration des Records und einen repäsentstiven Teil des Ini-Files.

Ich habe die Frage zur Deklaration und ein Beispiel der INI-Datei hinzugefügt.

himitsu 6. Jul 2022 13:34

AW: einen Datensatzmitgliedsnamen dynamisch zuweisen
 
Die Datenstruktur ändern
und gleiche Teile zusammenfassen?
(und dann nachfolgend den größten Teil ignorieren)

Delphi-Quellcode:
// nicht
ini.basic.path_A := pars[1]
ini.basic.path_B := pars[1]
// sondern
ini.basic.A.path := pars[1]
ini.basic.B.path := pars[1]

// für Objekte statt Records ... bei Records andersrum, also erst den Temp-Record füllen und dann zuweisen
if pars[0] = 'B' then X := ini.basic.B;
X.path := pars[1];





Delphi-Quellcode:
//if pars[0] = 'first_frame' then k := 'first_'+group
//else if pars[0] = 'end_frame' then k := 'last_'+group
//else if pars[0] = 'first_filename' then k := 'start_name_'+group
//else if pars[0] = 'path' then k := 'path_'+group
//else if pars[0] = 'check_if_files_exist' then k := 'check_files_exist_'+group
//else ; // was ist k, wenn nichts trifft?

// wozu den ersten Teil umbennen?
// sowas würde sich nur lohnen, wenn du anschließend mit diesen Namen via RTTI nach den Feldern suchen tätest.
TRTTIContext.Create.GetType(TIniBasicRecordIrgendwas).GetField(k).SetValue(ini.basic, pars[1]); // abgesehn vom check_if_files_exist
// es gibt auch Funktionen/Klassen/Frameworks, z.B. für INI/XML/JSON zu Record/Klasse, auch inkl. Umbenennen von SpeicherName zu FeldName

k := pars[0] + group;
if group = 'A' then begin
  if k = 'path_A' then ini.basic.path_A := pars[1]
  else if k = 'first_frame_A' then ini.basic.first_A := pars[1]
  else if k = 'end_frame_A' then ini.basic.last_A := pars[1]
  else if k = 'first_filename_A' then ini.basic.start_name_A := pars[1]
  else if k = 'check_if_files_exist_A' then ini.basic.check_files_exist_A := true;
end else if group = 'B' then begin
  if k = 'path_B' then ini.basic.path_B := pars[1]
  else if k = 'first_frame_B' then ini.basic.first_B := pars[1]
  else if k = 'end_frame_B' then ini.basic.last_B := pars[1]
  else if k = 'first_filename_B' then ini.basic.start_name_B := pars[1]
  else if k = 'check_if_files_exist_B' then ini.basic.check_files_exist_B := true;
end;
end; // ein end zuviel?
wozu nochmal die group extra vergleichen, wenn die schon in K enthalten ist?
Delphi-Quellcode:
k := pars[0] + group;
if k = 'path_A' then ini.basic.path_A := pars[1]
else if k = 'first_A' then ini.basic.first_A := pars[1]
else if k = 'last_A' then ini.basic.last_A := pars[1]
else if k = 'start_name_A' then ini.basic.start_name_A := pars[1]
else if k = 'check_files_exist_A' then ini.basic.check_files_exist_A := true
else if k = 'path_B' then ini.basic.path_B := pars[1]
else if k = 'first_B' then ini.basic.first_B := pars[1]
else if k = 'last_B' then ini.basic.last_B := pars[1]
else if k = 'start_name_B' then ini.basic.start_name_B := pars[1]
else if k = 'check_files_exist_B' then ini.basic.check_files_exist_B := true;
bzw.
Delphi-Quellcode:
case IndexText(pars[0] + group, ['path_A', 'first_A', 'last_A' , 'start_name_A' , 'check_files_exist_A' , 'path_B' , 'first_B' , 'last_B' , 'start_name_B', 'check_files_exist_B']) oF
  0: ini.basic.path_A := pars[1];
  1: ini.basic.first_A := pars[1];
  2: ini.basic.last_A := pars[1];
  3: ini.basic.start_name_A := pars[1];
  4: ini.basic.check_files_exist_A := true;
  5: ini.basic.path_B := pars[1];
  6: ini.basic.first_B := pars[1];
  7: ini.basic.last_B := pars[1];
  8: ini.basic.start_name_B := pars[1];
  9: ini.basic.check_files_exist_B := true;
end;


oder wozu unnötig umbenennen (Group anhängen), wenn die Groups eh getrennt behandelt werden?
Delphi-Quellcode:
//if pars[0] = 'first_frame' then k := 'first'
//else if pars[0] = 'end_frame' then k := 'last'
//else if pars[0] = 'first_filename' then k := 'start_name'
//else if pars[0] = 'path' then k := 'path'
//else if pars[0] = 'check_if_files_exist' then k := 'check_files_exist';

if group = 'A' then begin
  if pars[0] = 'path' then ini.basic.path_A := pars[1]
  else if pars[0] = 'first_frame' then ini.basic.first_A := pars[1]
  else if pars[0] = 'end_frame' then ini.basic.last_A := pars[1]
  else if pars[0] = 'first_filename' then ini.basic.start_name_A := pars[1]
  else if pars[0] = 'check_if_files_exist' then ini.basic.check_files_exist_A := true;
end else if group = 'B' then begin
  if k = 'path' then ini.basic.path_B := pars[1]
  else if pars[0] = 'first_frame' then ini.basic.first_B := pars[1]
  else if pars[0] = 'end_frame' then ini.basic.last_B := pars[1]
  else if pars[0] = 'first_filename' then ini.basic.start_name_B := pars[1]
  else if pars[0] = 'check_if_files_exist' then ini.basic.check_files_exist_B := true;
end;
bzw.
Delphi-Quellcode:
i := IndexText(pars[0] + group, ['path', 'first', 'last', 'start_name', 'check_files_exist']);
case group of
  'A':
    case i oF
      0: ini.basic.path_A := pars[1];
      1: ini.basic.first_A := pars[1];
      2: ini.basic.last_A := pars[1];
      3: ini.basic.start_name_A := pars[1];
      4: ini.basic.check_files_exist_A := true;
    end;
  'B':
    case i oF
      0: ini.basic.path_B := pars[1];
      1: ini.basic.first_B := pars[1];
      2: ini.basic.last_B := pars[1];
      3: ini.basic.start_name_B := pars[1];
      4: ini.basic.check_files_exist_B := true;
    end;
end;

neumimnemecky 6. Jul 2022 17:04

AW: einen Datensatzmitgliedsnamen dynamisch zuweisen
 
Danke, aber
"IndexText" Problem in der D7 [Error]: Undeclared identifier: 'IndexText'.

himitsu 6. Jul 2022 17:17

AW: einen Datensatzmitgliedsnamen dynamisch zuweisen
 
Zitat:

Zitat von neumimnemecky (Beitrag 1508491)
Problem in der D7

Wer macht denn sowas?

https://www.embarcadero.com/de/products/delphi/starter

Diese Funktionen gibt es bestimmt mindestens seit 2009 2006, also kurz nach D7, aber vielleicht auch schon im Delphi 7, wenn man die passende Unit einbindet? :angle:
Aktuell ist es in der System.StrUtils bzw. StrUtils ... aber mit der Zeit wurden auch Units umbenannt, bzw. Funktion in andere Units verschoben.

Delphi-Referenz durchsuchenStrUtils.IndexText (case-insensitive, also quasi mit einem AnsiUpperCase drumrum)
Delphi-Referenz durchsuchenStrUtils.IndexStr (case-sensitive)
Die gucken einfach nur in einem Array, ob/wo das da drin steht.

CASE kann ja leider im Delphi nur Ordinal und keine Strings, so wie nahezu jede andere Sprache :cry:

Delphi.Narium 6. Jul 2022 17:36

AW: einen Datensatzmitgliedsnamen dynamisch zuweisen
 
Delphi 7 kennt aber AnsiIndexText (in der Unit StrUtils zu finden).

neumimnemecky 6. Jul 2022 18:09

AW: einen Datensatzmitgliedsnamen dynamisch zuweisen
 
Viele Danke, daher habe ich den Code ein wenig geändert, um die Leistung zu steigern:

Code:
if group = 'A' then
 case AnsiIndexText(pars[0]+'_A', ['path_A', 'first_frame_A', 'end_frame_A' , 'first_filename_A' , 'check_if_files_exist_A']) oF
   0: ini.basic.A.path := pars[1];
   1: ini.basic.A.first := pars[1];
   2: ini.basic.A.last := pars[1];
   3: ini.basic.A.start_name := pars[1];
   4: ini.basic.A.check_files_exist := true;
 end
else
if group = 'B' then
 case AnsiIndexText(pars[0]+'_B', ['path_B' , 'first_frame_B' , 'end_frame_B' , 'first_filename_B', 'check_if_files_exist_B']) oF
   0: ini.basic.B.path := pars[1];
   1: ini.basic.B.first := pars[1];
   2: ini.basic.B.last := pars[1];
   3: ini.basic.B.start_name := pars[1];
   4: ini.basic.B.check_files_exist := true;
 end;
Es ist eine schöne Lösung.

himitsu 6. Jul 2022 18:29

AW: einen Datensatzmitgliedsnamen dynamisch zuweisen
 
Delphi-Quellcode:
(pars[0]+'_B', ['path_B' , 'first_frame_B' , ...


Delphi-Quellcode:
(pars[0], ['path' , 'first_frame' , ...
:stupid:


Schneller ist es nur bedingt ... eher fast gleich schnell oder vielleicht eine Millisekunde langsamer (ein Funktionsaufruf, aber gleich viele String-Vergleiche),
aber es macht den Code kürzer und ohne die viele IF....THEN dazwischen auch etwas übersichlicher.

Hier die
Delphi-Quellcode:
123:
als Konstante oder mit
Delphi-Quellcode:
{Name}123:
, erspart sich, da der Kommentar/Name bereits als
Delphi-Quellcode:
.path :=
dran steht.

neumimnemecky 6. Jul 2022 18:42

AW: einen Datensatzmitgliedsnamen dynamisch zuweisen
 
Zitat:

Zitat von himitsu (Beitrag 1508500)
Delphi-Quellcode:
(pars[0]+'_B', ['path_B' , 'first_frame_B' , ...


Delphi-Quellcode:
(pars[0], ['path' , 'first_frame' , ...
:stupid:


Schneller ist es nur bedingt ... eher fast gleich schnell oder vielleicht eine Millisekunde langsamer (ein Funktionsaufruf, aber gleich viele String-Vergleiche),
aber es macht den Code kürzer und ohne die viele IF....THEN dazwischen auch etwas übersichlicher.

Hier die
Delphi-Quellcode:
123:
als Konstante oder mit
Delphi-Quellcode:
{Name}123:
, erspart sich, da der Kommentar/Name bereits als
Delphi-Quellcode:
.path :=
dran steht.


Den letzten Satz verstehe ich nicht. Aber eine Millisekunde langsamer wäre viel. Hatten Sie nicht eine Mikrosekunde im Sinn?


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:08 Uhr.
Seite 1 von 4  1 23     Letzte »    

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