Recent

Author Topic: User tags/masks as index of StringsList  (Read 4717 times)

TomTom

  • Full Member
  • ***
  • Posts: 170
User tags/masks as index of StringsList
« on: March 14, 2018, 11:24:16 am »
I don't know if named my problem correctly in Subject of my topic but here's more detailed explanation of what I want.

So I have StringList with some strings  ;). For example:
Code: Pascal  [Select][+][-]
  1. sl.strings[0]:='Value1';
  2. sl.strings[1]:='Value2';
  3. sl.strings[2]:='Value3';
  4. sl.strings[3]:='Value4';
  5.  

I have 1 Edit field where user is supposed to enter a mask for example:
Code: Pascal  [Select][+][-]
  1. %value0%%value3%%value2%%value1%
  2.  

I have a button and If user presses it then for example in Memo1 a line will be added like this

Code: Pascal  [Select][+][-]
  1. string from sl.Strings[0] +string from sl.Strings[3] +string from sl.Strings[2] +string from sl.Strings[1]

So my program read the index for string from a tag/mask and adds it to memo1.

I'm aware of my problems with explaining what I need in english so.... please ask if You don't understand what I wrote :P.

Thaddy

  • Hero Member
  • *****
  • Posts: 14197
  • Probably until I exterminate Putin.
Re: User tags/masks as index of StringsList
« Reply #1 on: March 14, 2018, 11:39:50 am »
Code: Pascal  [Select][+][-]
  1. {$mode delphi}{$R+}
  2. uses sysutils, classes;
  3. var
  4.   sl:TStringlist;
  5. begin
  6.   sl := TStringlist.Create;
  7.   try
  8.     sl.Add('Value1'); //0
  9.     sl.Add('Value2'); //1
  10.     sl.Add('Value3'); //2
  11.     sl.Add('Value4'); //3
  12.     writeln(sl[0],sl[3],sl[2],sl[1]);
  13.     // or
  14.     writeln(format('%s,%s,%s,%s',[sl[0],sl[3],sl[2],sl[1]]));
  15.   finally
  16.     sl.Free;
  17.   end;
  18. end.
« Last Edit: March 14, 2018, 11:44:12 am by Thaddy »
Specialize a type, not a var.

rvk

  • Hero Member
  • *****
  • Posts: 6110
Re: User tags/masks as index of StringsList
« Reply #2 on: March 14, 2018, 11:49:38 am »
Why not just let the user enter 0;3;2;1
Or do you need other text in there too?

You could also do %0%other text%3%again other text%2% - %1%
In that case you can just look for %index% and replace it with the string index.

There are two ways to tackle this:
1) Loop through all the strings in the TStringList and replace %index% with the string content on that index
2) Extract all %index% from the mask and check if index is only numbers/valid index and replace it with the corresponding string.

Efficiency would depend on how large the TStringList is. If you have thousands of entries in the list you want to go for option 2. If the TStringList is limited option 1 would be easiest to program.

Option 1 would be:
Code: Pascal  [Select][+][-]
  1. Masked := '%0%other text%3%again other text%2% - %1%';
  2. for I := 0 to sl.Count - 1 do
  3.   Masked := StringReplace(Masked, '%' + I.ToString + '%', sl[I], [rfReplaceAll]);
Note: If you have %index% where index doesn't exist in the TStringList, it will not be replaced so you would end up with %index% in the end-result. If that is a problem go with option 2.

@Thaddy, how is that a dynamic solution for when the user enters something else in a different order in the masked-edit?

I have 1 Edit field where user is supposed to enter a mask for example:
...
I have a button and If user presses it then for example in Memo1 a line will be added like this
« Last Edit: March 14, 2018, 11:52:07 am by rvk »

Thaddy

  • Hero Member
  • *****
  • Posts: 14197
  • Probably until I exterminate Putin.
Re: User tags/masks as index of StringsList
« Reply #3 on: March 14, 2018, 11:53:05 am »
@Rik I simply kept his/her order...
Another possibility is something like this, btw (trunk):
Code: Pascal  [Select][+][-]
  1. {$mode delphi}{$R+}
  2. uses sysutils;
  3. var
  4.   sl:Tarray<String>;
  5. begin
  6.   sl := ['Value1','Value2','Value3','Value4'];
  7.   writeln(sl[0],sl[3],sl[2],sl[1]);
  8.   // or
  9.   writeln(format('%s,%s,%s,%s',[sl[0],sl[3],sl[2],sl[1]]));
  10. end.

Then there is also our templates unit  O:-) O:-) You and me probably know 100+ different ways to solve this, but pseudo code is open to interpretation.
Specialize a type, not a var.

rvk

  • Hero Member
  • *****
  • Posts: 6110
Re: User tags/masks as index of StringsList
« Reply #4 on: March 14, 2018, 11:55:38 am »
@Rik I simply kept his/her order...
The point is that the order (and input) is given by a random user and would be different each time. You can't expect it to be the same order as given by the example.

I have 1 Edit field where user is supposed to enter a mask for example:
...
I have a button and If user presses it then for example in Memo1 a line will be added like this

So you should read that order from the input given by a user.

Thaddy

  • Hero Member
  • *****
  • Posts: 14197
  • Probably until I exterminate Putin.
Re: User tags/masks as index of StringsList
« Reply #5 on: March 14, 2018, 11:57:55 am »
Well. That's the easy part...
Specialize a type, not a var.

TomTom

  • Full Member
  • ***
  • Posts: 170
Re: User tags/masks as index of StringsList
« Reply #6 on: March 14, 2018, 12:30:32 pm »
Well, thank You for Your answer :) But I don't think this is what I wanted to achieve

I'll try to explain it simpler

I have a stringlist
Code: Pascal  [Select][+][-]
  1. sl.strings[0]:='TOMEK';
  2. sl.strings[1]:='DOM';
  3. sl.strings[2]:='1293;
  4.  

User writes a pattern in the Edit field for example
Code: Pascal  [Select][+][-]
  1. %index2%%index0%%index1%
  2.  
Or user can enter any combination he want. 
for example
Code: Pascal  [Select][+][-]
  1. %index2%%index0%%index1%%index2%%index2%%index1%
  2.  
I don't know what pattern user want's. Depending on what user pattern is, the proper output string is created by getting string from corresponding StringList index and added to Memo.

For example:

My Strings list looks like the above one
User enters a pattern
Code: Pascal  [Select][+][-]
  1. %index2%%index0%%index1%%index2%%index1%

into Edit1

If button is clicked then this line is added to Memo1:
Code: Pascal  [Select][+][-]
  1. 1293TOMEKDOM1293DOM

After that user decides that he want to change his pattern and enters something like this into Edit1
Code: Pascal  [Select][+][-]
  1. %index0%%index0%%index1%%index0%%index2%%index2%%index1%

So the output would be:
 
Code: Pascal  [Select][+][-]
  1. TOMEKTOMEKDOM19231923DOM

[EDIT]:
Yes I would like to let user input something like this

Code: Pascal  [Select][+][-]
  1. %index0%_%index0%_%index1%_%index0%

so the ouput string would like like this in my example
Code: Pascal  [Select][+][-]
  1. TOMEK_TOMEK_DOM_TOMEK



rvk

  • Hero Member
  • *****
  • Posts: 6110
Re: User tags/masks as index of StringsList
« Reply #7 on: March 14, 2018, 12:33:56 pm »
so the ouput string would like like this in my example
Code: Pascal  [Select][+][-]
  1. TOMEK_TOMEK_DOM_TOMEK
Option 1 mentioned in my answer will do exactly what you want.

If you really want index before 1, 2 etc then you can change this
'%' + I.ToString + '%'
into this
'%index' + I.ToString + '%'

TomTom

  • Full Member
  • ***
  • Posts: 170
Re: User tags/masks as index of StringsList
« Reply #8 on: March 14, 2018, 12:43:39 pm »
so the ouput string would like like this in my example
Code: Pascal  [Select][+][-]
  1. TOMEK_TOMEK_DOM_TOMEK
Option 1 mentioned in my answer will do exactly what you want.

If you really want index before 1, 2 etc then you can change this
'%' + I.ToString + '%'
into this
'%index' + I.ToString + '%'


I was trying to write my answer so long so You guys replied few times already :P
Yes, thank You I'm looking into it right now :)

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: User tags/masks as index of StringsList
« Reply #9 on: March 14, 2018, 01:17:27 pm »
Code: Pascal  [Select][+][-]
  1. uses sysutils;
  2. begin
  3.   writeln(format('%0:S %1:S %0:S, %3:S, %2:S, %1:S, %S, %0:S',['1','2','3','4']));
  4. end.
  5.  
expected output
Code: [Select]
1 2 1 4 3 2 3 1
« Last Edit: March 14, 2018, 01:19:55 pm by taazz »
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

TomTom

  • Full Member
  • ***
  • Posts: 170
Re: User tags/masks as index of StringsList
« Reply #10 on: March 14, 2018, 01:34:52 pm »
RVK Solution works like a charm :) Now all I need to do is to reverse my string list :)

SymbolicFrank

  • Hero Member
  • *****
  • Posts: 1313
Re: User tags/masks as index of StringsList
« Reply #11 on: March 14, 2018, 01:50:28 pm »
You might want to look at TStringList.CommaText.

TomTom

  • Full Member
  • ***
  • Posts: 170
Re: User tags/masks as index of StringsList
« Reply #12 on: March 14, 2018, 09:10:08 pm »
I solved this by using multiple times ReplaceString function for each parameter I want the user to be able to use... I don't know if it's good but it works :P



Quote
Ok. So I managed to create program which can rename files using the folder structure with possibility to mix them in the way that user wants... For example:
Code: Pascal  [Select][+][-]
  1. C:\MainFolder\30\0\23\943\1\TextFileA.txt
  2. C:\MainFolder\30\0\23\943\1\TextFile033.txt
  3. C:\MainFolder\30\0\23\943\1\TextFile03a.txt
  4. C:\MainFolder\30\0\23\943\1\TextFile0341.txt
  5. C:\MainFolder\35\123\23\943\1\TextFileB.txt
  6. C:\MainFolder\35\123\23\943\1\TextFileGF.txt
  7. C:\MainFolder\35\123\23\943\1\TextFileBK.txt
  8. C:\MainFolder\35\123\23\943\1\TextFileOD.txt
  9.  
So after running those files through my program  with this patter %folder5%_%folder4%_%folder3%_%folder2%_%folder1%, the files will be named like this:
Code: Pascal  [Select][+][-]
  1. C:\MainFolder\30\0\23\943\1\30_0_23_943_1_0001.txt
  2. C:\MainFolder\30\0\23\943\1\30_0_23_943_1_0002.txt
  3. C:\MainFolder\30\0\23\943\1\30_0_23_943_1_0003.txt.
  4. C:\MainFolder\30\0\23\943\1\30_0_23_943_1_0004.txt
  5.  
  6. C:\MainFolder\35\123\23\943\1\35_123_23_943_1_0001.txt
  7. C:\MainFolder\35\123\23\943\1\35_123_23_943_1_0002.txt
  8. C:\MainFolder\35\123\23\943\1\35_123_23_943_1_0003.txt
  9. C:\MainFolder\35\123\23\943\1\35_123_23_943_1_0004.txt

number at the end of the file, for now is hard coded and will be always added.
I would like to give user a possibility to decide if he wants this counter and WHERE he wants it (ofcourse he wants it :P! otherwise files will be overwritten :P). But hey.. I want to do something like this.

User enters a pattern like this:
Code: Pascal  [Select][+][-]
  1. %folder5%_%folder4%_%folder3%_%folder2%_%folder1%_%COUNTER%

Now I'm using solution that RVK provided and its good. But it uses StringReplace. So how can I add more masks to Pattern? For example %COUNTER% to add counter or %EXT% to add extension of the file.
 
[/s]
« Last Edit: March 14, 2018, 09:22:12 pm by TomTom »

jamie

  • Hero Member
  • *****
  • Posts: 6090
Re: User tags/masks as index of StringsList
« Reply #13 on: March 14, 2018, 10:22:59 pm »
 What you are doing is simply putting in a variable name that will translate to a index number of course. 
 
  and to do so effectively you should write  parser for it that toggles a Boolean type to indicate if you
are between a pair of &...& and if so, accumulate a String from that. each time you hit a "&" you
toggle the Toggle Flag..
 
 If inputChar = '&' Then ToggleFlag := Not ToggleFlag;

 Then while you are concating the main string, you test for this flag..

 if flag is TRUE then you are concating a search string, if not, then you are concating the
main string..
 
 each time you toggle this flag, you need to test it, if its false after a toggle this means you just
finished a build of a search string, in which case you now use that results to search the list..

etc..

 if you need an example I can provide one..

       
       

 
The only true wisdom is knowing you know nothing

TomTom

  • Full Member
  • ***
  • Posts: 170
Re: User tags/masks as index of StringsList
« Reply #14 on: March 14, 2018, 10:44:12 pm »
Maybe it would be easier for me to understand when You show me example. But either way My program works quite fast and without problems and as intended,even on large number of files (3000+) :). But please do show me example :) Maybe I could put Your solution in future version :) I'm always eager to learn new stuff :)
 
What you are doing is simply putting in a variable name that will translate to a index number of course. 
 
  and to do so effectively you should write  parser for it that toggles a Boolean type to indicate if you
are between a pair of &...& and if so, accumulate a String from that. each time you hit a "&" you
toggle the Toggle Flag..
 
 If inputChar = '&' Then ToggleFlag := Not ToggleFlag;

 Then while you are concating the main string, you test for this flag..

 if flag is TRUE then you are concating a search string, if not, then you are concating the
main string..
 
 each time you toggle this flag, you need to test it, if its false after a toggle this means you just
finished a build of a search string, in which case you now use that results to search the list..

etc..

 if you need an example I can provide one..

       
       
« Last Edit: March 14, 2018, 10:45:49 pm by TomTom »

 

TinyPortal © 2005-2018