【问题标题】:delphi hashmap?德尔福哈希表?
【发布时间】:2011-04-04 08:14:16
【问题描述】:

我有 java 代码从文本文件填充哈希图。
HashMap<String, String[]> data = new HashMap<String, String[]>();

我用它来制作键值对。这些值是一个字符串数组。我必须遍历键值对的所有可能组合(因此还必须遍历字符串 [] 数组)。这适用于java,但现在我必须将它移植到delphi。可以这样做吗?如何? 谢谢!

【问题讨论】:

  • 使用 Generics.Collections.TDictionary

标签: delphi hashmap


【解决方案1】:

在 Delphi 2009 及更高版本中,您可以通过 Generics.Collections 使用 TDictionary<string, TStringlist>

在旧版本中,您可以使用 TStringlist,其中 TStringlist 中的每个项目都有一个 TStrings 类型的关联对象值。

Docwiki 有一个页面到get started with TDictionary

【讨论】:

  • 哦,谢谢。这看起来不错。有迭代器吗?在java中我使用递归方法,它给了我键值对的每个组合(注意:值是delphi-context中的字符串列表......)
  • 可以使用for in来枚举键值对
  • 我的代码看起来像这样(在 stackoverflow 上找到它):stackoverflow.com/questions/5322948/recursive-iterate-hashmap。这如何转化为 delphi?
  • @someuser:看看我的补充,也许这有助于开始
【解决方案2】:

从 Delphi 6 开始,预定义的容器类集合包括 TBucketList 和 TObjectBucketList。这两个列表是关联的,这意味着它们有一个键和一个实际条目。密钥用于识别项目并搜索它们。要添加项目,请使用两个参数调用 Add 方法:键和数据。当您使用 Find 方法时,您传递密钥并检索数据。通过使用 Data 数组属性,将键作为参数传递,可以实现相同的效果。

【讨论】:

    【解决方案3】:

    如果您有旧版本的 Delphi(Delphi 6 及更高版本),您也可以使用 record动态数组,然后使用我们的 TDynArray 或 @987654324 @wrappers 用动态数组记录的一个字段创建一个字典。见this unit

    TDynArrayHashed 包装器的开发速度很快。

    这里是一些示例代码(来自提供的单一测试):

    var ACities: TDynArrayHashed;
        Cities: TCityDynArray;
        CitiesCount: integer;
        City: TCity;
        added: boolean;
        N: string;
        i,j: integer;
    const CITIES_MAX=200000;
    begin
      // valide generic-like features
      // see http://docwiki.embarcadero.com/CodeExamples/en/Generics_Collections_TDictionary_(Delphi)
      ACities.Init(TypeInfo(TCityDynArray),Cities,nil,nil,nil,@CitiesCount);
      (...)
      Check(ACities.FindHashed(City)>=0);
      for i := 1 to 2000 do begin
        City.Name := IntToStr(i);
        City.Latitude := i*3.14;
        City.Longitude := i*6.13;
        Check(ACities.FindHashedAndUpdate(City,true)=i+2,'multiple ReHash');
        Check(ACities.FindHashed(City)=i+2);
      end;
      ACities.Capacity := CITIES_MAX+3; // make it as fast as possible
      for i := 2001 to CITIES_MAX do begin
        City.Name := IntToStr(i);
        City.Latitude := i*3.14;
        City.Longitude := i*6.13;
        Check(ACities.FindHashedAndUpdate(City,true)=i+2,'use Capacity: no ReHash');
        Check(ACities.FindHashed(City.Name)=i+2);
      end;
      for i := 1 to CITIES_MAX do begin
        N := IntToStr(i);
        j := ACities.FindHashed(N);
        Check(j=i+2,'hashing with string not City.Name');
        Check(Cities[j].Name=N);
        CheckSame(Cities[j].Latitude,i*3.14);
        CheckSame(Cities[j].Longitude,i*6.13);
      end;
    end;
    

    所以对于你的问题:

    type
      TMyMap = record
        Key: string;
        Value: array of string;
      end;
      TMyMapDynArray = array of TMyMap;
    
    var
      Map: TMyMap;
      Maps: TMyMapDynArray;
      MapW: TDynArrayHashed;
      key: string;
      i: integer;
    begin
      MapW.Init(TypeInfo(TMyMapDynArray),Maps);
      Map.Key := 'Some key';
      SetLength(Map.Value,2);
      Map.Value[0] := 'One';
      Map.Value[1] := 'Two';
      MapW.FindHashedAndUpdate(Map,true); // ,true for adding the Map content
      key := 'Some key';
      i := MapW.FindHashed(key);
      // now i=0 and Maps[i].Key=key
      for i := 0 to MapW.Count-1 do // or  for i := 0 to high(Maps) do
        with Maps[i] do
        // now you're enumerating all key/value pairs
    end;
    

    【讨论】:

    • 我刚刚将这个包装器用于我的 .map 文件阅读器,它就像一个魅力。非常快速和容易使用。 .map 文件立即被读取,符号名称使用快速散列添加到内部列表中。见this link
    猜你喜欢
    • 1970-01-01
    • 2014-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-02
    • 2011-10-04
    相关资源
    最近更新 更多