delphi字典迭代

发布于 2024-10-31 02:18:46 字数 1462 浏览 3 评论 0原文

早上好!

我用字符串作为值和几个字符串作为值填充字典 TDictionary (delphi-collections-unit)。 例如:

  • 姓名 = john、lisa、stan
  • 技能 = 读、写、说
  • 年龄 = 12、14、16

(当然没有“,”)。 我需要的是迭代这个字典并将值与键相乘。 输出应类似于

  • 名称 = 约翰技能 = 读取年龄 = 12
  • 名称 = 约翰技能 = 读取年龄 = 14
  • 名称 = 约翰技能 = 读取年龄 = 16
  • 名称 = 约翰技能 = 写入年龄 = 12
  • 名称 = 约翰技能 = 写入年龄 = 14
  • 名称= 约翰技能 = 写年龄 = 16
  • ...
  • 名字 = 丽莎技能 = 读年龄 = 12
  • ...
  • 名字 = 斯坦技能 = 说话年龄 = 16

所以每个组合。 我怎样才能这样做?键的数量是动态的,tstringlist 的大小也是动态的。 谢谢!现在已经解决了……

现在是范围的问题。以下是填充字典的过程。子分割和分割字符串是字符串列表,它们在过程结束时被释放。字典是在过程块之后创建的(在 main 中?它是如何调用的?),调用填充方法,然后我想像代码示例中那样进行递归,但字典中没有值... 。

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;//

g'morning!

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

  • names = john, lisa, stan
  • skills = read, write, speak
  • ages = 12, 14, 16

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

  • names = john skills = read ages = 12
  • names = john skills = read ages = 14
  • names = john skills = read ages = 16
  • names = john skills = write ages = 12
  • names = john skills = write ages = 14
  • names = john skills = write ages = 16
  • ...
  • names = lisa skills = read ages = 12
  • ...
  • names = stan skills = speak ages = 16

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;//

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

许一世地老天荒 2024-11-07 02:18:46

使用 TDictionary会使您想要的变得有点复杂,因为这意味着键的数量可变。如果不是因为键的数量可变,则不需要字典,只需迭代 3 个 TStringList 即可。

也就是说,您遇到了经典的“生成所有排列”问题。它可以使用递归或回溯来解决。递归更容易实现,回溯使用更少的堆栈空间。选择权在你。这是一个完整的控制台应用程序,它完成了整个过程,从初始化字典、填充字典到使用递归函数生成所有排列。

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.

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.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文