【问题标题】:delphi dictionary iteratingdelphi字典迭代
【发布时间】:2011-04-07 07:42:04
【问题描述】:

早安!

我用字符串作为值和几个字符串作为值填充字典TDictionary<String, TStringlist>(delphi-collections-unit)。 类似:

  • 名字 = 约翰、丽莎、斯坦
  • 技能 = 读、写、说
  • 年龄 = 12、14、16

(当然没有“,”)。 我需要的是迭代这个字典并用键乘以值。 输出应该像

  • 名字 = 约翰技能 = 阅读年龄 = 12
  • 名字 = 约翰技能 = 阅读年龄 = 14
  • 名字 = 约翰技能 = 阅读年龄 = 16
  • 名字 = 约翰技能 = 写年龄 = 12
  • 名字 = 约翰技能 = 写年龄 = 14
  • 名字 = 约翰技能 = 写年龄 = 16
  • ...
  • 名字 = lisa 技能 = 阅读年龄 = 12
  • ...
  • 名字 = 斯坦技能 = 说话年龄 = 16

所以每个组合。 我该怎么做?键的数量是动态的,tstringlist 的大小也是动态的。 谢谢!现在解决了...

现在是范围的问题。以下是填充字典的过程。 subsplits 和 splitstring 是字符串列表,它们在过程结束时被释放。 dict是在程序块之后创建的(在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;//

【问题讨论】:

  • @stanislav,我编辑了您的问题以使其易于阅读。下次请自己做。当你写你的问题时,你的右侧有一个帮助屏幕,它解释了降价和底部的实时预览,这样你就知道你的问题在发布后会是什么样子。
  • 你是对的。我也想编辑它,但你更快。谢谢!
  • @stanislav,您的示例与您的问题不符。你没有做“所有组合”,你的最后一个示例行是“lisa”、“read”和“12”。如果该示例是names=stan, skills=speak, ages=16,则解决方案将很简单;就目前而言,我不确定你想要什么!
  • 啊,好的!我写了“等等”来说明清楚,对不起!是的,最后一行应该是 names=stan,skills=speak,ages=16,yes。
  • 这是作业吗?如果是这样,请使用homework 标签。

标签: delphi loops tdictionary


【解决方案1】:

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

也就是说,您遇到了经典的“生成所有排列”问题。可以使用递归或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.

【讨论】:

  • 完美运行,谢谢! 3 个 for 循环很清楚,是的。
  • 这是您的第一个问题,如果您认为它解决了您的问题并且是给出的最佳答案,请不要忘记接受答案。
  • 该死的,是的。你的代码有效。但我的没有......我在一个程序中填写字典。我在我的里面试过你的代码。如果我迭代 proc 中的值,它们是正确的。如果我在开始后这样做,则值是错误的。代码是:parsefile是一个过程,填充dict(全局变量)。但是离开程序时这些值似乎丢失了......为什么?
  • 问题的最可能原因是变量作用域(也许你指的是不同的dict)和生命周期问题(也许你在释放它之后指的是dict) .如果您无法发现错误,请尝试将代码添加到问题中,以便我们查看。
猜你喜欢
  • 2021-06-22
  • 1970-01-01
  • 2021-08-26
  • 2013-12-03
  • 1970-01-01
  • 2014-05-29
  • 2017-10-29
  • 2013-02-01
  • 1970-01-01
相关资源
最近更新 更多