2011-04-07 180 views
1

g'morning!delphi字典迭代

我填充字典TDictionary<String, TStringlist>(delphi-collections-unit),字符串作爲值和幾個字符串作爲值。 類似:

  • 名稱=約翰,麗莎,斯坦
  • 技能=讀,寫,說
  • 年齡= 12,14,16

(沒有 「」 當然, )。 我需要的是迭代這個字典,並用這些鍵乘以數值。 輸出應該像

  • 名稱=約翰技能=讀年齡= 12個
  • 名稱=約翰技能=讀年齡= 14個
  • 名稱=約翰技能=讀年齡= 16個
  • 名稱=約翰技能=寫年齡= 12個
  • 名稱=約翰技能=寫年齡= 14個
  • 名稱=約翰技能=寫年齡= 16
  • ...
  • 名=麗莎技能=讀年齡= 12
  • ...
  • 名=斯坦技能=說話的年齡= 16

所以每一個組合。 我該怎麼做?鍵的數量是動態的,tstringlist的大小也是動態的。 謝謝!現在解決...

現在的問題與範圍。以下是填寫字典的程序。 subsplits和splitstring是字符串列表,在程序結束時被釋放。該字典是在程序塊(在main?它是如何調用的?)之後創建的,填充方法被調用,然後我想像代碼示例中那樣執行遞歸,但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;// 
+4

@stanislav,我編輯你的問題,使其可讀性。下次,請自己動手。當你寫下你的問題時,你的右邊有一個幫助屏幕,解釋了降價和底部的實時預覽,這樣你就可以知道你的問題一旦發佈就會如何。 – 2011-04-07 07:47:29

+0

你是對的。我也想編輯它,但你更快。謝謝! – soulbrother 2011-04-07 07:49:09

+0

@stanislav,你的例子與你的問題不符。你不是在做「每一種組合」,你最後的例子是「lisa」,「read」和年齡「12」。如果這個例子是'names = stan,skills = speak,age = 16',那麼解決方案很簡單;現在,我不知道你想要什麼! – 2011-04-07 07:50:07

回答

5

你想由位通過使用TDictionary<string, TStringList>的複雜,因爲這意味着變量的數字鍵的是什麼。如果不是可變數目的鍵,則不需要字典,而只需迭代3個TStringLists。

這就是說,你有經典的「產生所有排列」問題。它可以使用遞歸或backtracking來解決。遞歸更容易實現,回溯使用更少的堆棧空間。這是你的選擇。這是一個完整的控制檯應用程序,完成整個交易,從初始化字典,填充字典,使用遞歸函數生成所有排列。

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. 
+0

完美的作品,謝謝! 3個for-loops非常清晰,是的。 – soulbrother 2011-04-07 08:48:36

+0

由於這是你的第一個問題,如果你認爲它解決了你的問題,並且是給出的最佳答案,請不要忘記接受答案。 – Runner 2011-04-07 08:49:33

+0

該死的,是的。你的代碼工作。但我的不是......我在程序中填寫字典。我在我的內部試過你的代碼。如果我重複proc中的值,他們是正確的。如果我在開始後這樣做,這些值是錯誤的。代碼是:parsefile是一個過程,填充了dict(全局變量)。但是離開程序時價值似乎會丟失......爲什麼? – soulbrother 2011-04-07 10:04:42