46497

delphi dictionary iterating

g'morning!

i fill a dictionary TDictionary<String, TStringlist> (delphi-collections-unit) with strings as values and several strings as values. something like:

    <li>names = john, lisa, stan</li> <li>skills = read, write, speak</li> <li>ages = 12, 14, 16</li> </ul>

    (without "," of course). what i need is to iterate this dictionary and to multiply out the values with the keys. output should be like

      <li>names = john skills = read ages = 12</li> <li>names = john skills = read ages = 14</li> <li>names = john skills = read ages = 16</li> <li>names = john skills = write ages = 12</li> <li>names = john skills = write ages = 14</li> <li>names = john skills = write ages = 16</li> <li>...</li> <li>names = lisa skills = read ages = 12 </li> <li>...</li> <li>names = stan skills = speak ages = 16</li> </ul>

      so every combination. how can i do so? the number of keys is dynamic and so is the size of the tstringlist. thanks! SOLVED by now...

      now the problem with the scope. following is the procedure that fills the dict. the subsplits and the splitstring are stringlists, that get freed at the end of the procedure. the dict is created after the procedures-block (in main? how is it called?), the fill-method is called and then i want to do recursion like in the code-example but there are no values in the dict....

      while not Eof(testfile) do begin ReadLn(testfile, text); if AnsiContainsStr(text, '=') then begin Split('=', text, splitarray); splitarray[0] := trim(splitarray[0]); splitarray[1] := DeleteSpaces(splitarray[1]); if AnsiStartsStr('data', splitarray[0]) then begin split(' ', splitarray[0], subsplit1); splitarray[0]:=subsplit1[1]; split(',', splitarray[1], subsplit2); dict.Add(splitarray[0], subsplit2); for ValueName in dict.Values do begin for i := 0 to Valuename.Count - 1 do write('Values are : '+ Valuename[i]); writeln; end;// end;// end;// end;//

      Answer1:

      What you want is made a bit complicated by the use of the TDictionary<string, TStringList>, because that implies variable number of keys. If it weren't for the variable number of keys, you wouldn't need a dictionary and you'd simply iterate over 3 TStringLists.

      That said, you've got the classic "generate all permutations" problem. It can be solved using recursion or backtracking. Recursion is simpler to implement, backtracking uses less stack space. The choice is yours. Here's a complete console application that does the whole deal, from initializing the dictionary, populating the dictionary, generating all permutations using a recursive function.

      program Project23; {$APPTYPE CONSOLE} uses SysUtils, Classes, Generics.Collections; var Dict:TDictionary<string, TStringList>; L: TStringList; KeyName: string; KeysList: TStringList; // Help procedure, adds a bunch of values to a "Key" in the dictionary procedure QuickAddToDict(KeyName:string; values: array of string); var L: TStringList; s: string; begin // Try to get the TStringList from the dictionary. If we can't get it // we'll create a new one and add it to the dictionary if not Dict.TryGetValue(KeyName, L) then begin L := TStringList.Create; Dict.Add(KeyName, L); end; // Iterate over the values array and add stuff to the TStringList for s in values do L.Add(s); end; // Recursive routine to handle one KEY in the dictionary procedure HandleOneKey(KeyIndex:Integer; PrevKeys:string); var L:TStringList; i:Integer; Part: string; KeyName: string; begin KeyName := KeysList[KeyIndex]; L := Dict[KeyName]; for i:=0 to L.Count-1 do begin Part := KeyName + '=' + L[i]; if KeyIndex = (KeysList.Count-1) then WriteLn(PrevKeys + ' ' + Part) // This is a solution, we're at the last key else HandleOneKey(KeyIndex+1, PrevKeys + ' ' + Part); // Not at the last key, recursive call for the next key end; end; begin try Dict := TDictionary<string, TStringList>.Create; try // Add whatever you want to the Dict. // Using the helper routine to set up the dictionary faster. QuickAddToDict('names', ['john', 'lisa', 'stan']); QuickAddToDict('skills', ['read', 'write', 'speak']); QuickAddToDict('ages', ['12', '14', '16']); // Extract all the keys to a string list. Unfortunately the dictionary // doesn't offer a way to get a key name by index, so we have to use the // keys iterator to extract all keys first. KeysList := TStringList.Create; try for KeyName in Dict.Keys do KeysList.Add(KeyName); if KeysList.Count > 0 then begin // We got at least one key, we can start the recursive process. HandleOneKey(0, ''); end; finally KeysList.Free; end; WriteLn; WriteLn('Press ENTER to make the window go away'); ReadLn; finally // TDictionary doesn't own the keys or the values. Strings are managed types in // delphi, we don't need to worry about them, but we do need to free the TStringList's // We use the Values iterator for that! for L in Dict.Values do L.Free; Dict.Free; end; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end.

Recommend

  • Statement expected but Function found error in my function code
  • Why is TFormatSettings not behaving as expected?
  • Duck typing in Delphi 2007 (Continued)?
  • How do you handle spaces in variables when using C# interpolation?
  • node.js createWriteStream doesn't create new file on Heroku
  • Skip over levels of a directory when importing python package
  • Value cannot be null.Parameter name: stream error while reading the contents of embeddded file
  • Best way to validate and extend constructor parameters in Scala 2.10
  • How do I remove the last vowel in a string in Ruby?
  • Adding millions of nodes to neo4j spatial layer using cypher and apoc
  • How to Navigate from Initial UIViewController to UISplitViewController in Swift
  • Mixing cin and getline under Linux and Windows
  • How to check a string does not start with a number in Batch?
  • Using Regex to split XML string before and after match
  • How to make a dictionary from a text file with python
  • .htaccess mod rewriterule and ampersands
  • Android Studio cannot find resources when building for device with version > 5.0
  • C# “cannot assign field because it is a foreach iteration variable”
  • How to write xml into a file using MarkupBuilder
  • Table-per-type inheritance insert problem
  • How to bind comma separated list of values to List
  • Excel 2007: Format of email address from Outlook 2007
  • How to split row into many rows in postgresql
  • How can I count unique terms in a plaintext file case-insensitively?
  • Negated scanset in fscanf and EOF
  • Updating and removing unique join relationships in CakePHP
  • Python: Split a String Field into 3 Separate Fields using Lambda
  • Negating Regex PO BOX
  • how can I compare dates in array to find the earliest one?
  • Divide a $1 by 3 and adjusting 1 cent
  • How do I shift the decimal place in Python?
  • How to know when stdin is empty if it contains EOF?
  • MySQL WHERE-condition in procedure ignored
  • Web-crawler for facebook in python
  • trying to dynamically update Highchart column chart but series undefined
  • Benchmarking RAM performance - UWP and C#
  • Acquiring multiple attributes from .xml file in c#
  • How to CLICK on IE download dialog box i.e.(Open, Save, Save As…)
  • How can I remove ASP.NET Designer.cs files?
  • java string with new operator and a literal