Delphi t在创建示例代码期间填充字典

Delphi t在创建示例代码期间填充字典,delphi,Delphi,是否有人在其构造函数中填充了t字典的示例代码?您需要调用接收集合的类型为TEnumerable的参数 例如,假设我们有TDictionary。然后我们可以将TEnumerable的一个实例传递给构造函数。这类事情的一个例子是 因此,如果您已经有一个字典实例,您可以创建另一个,并使用第一个实例的内容对其进行初始化: Dict2 := TDictionary<string, Integer>.Create(Dict1); Dict2:=TDictionary.Create(Dict1)

是否有人在其构造函数中填充了
t字典的示例代码?

您需要调用接收
集合的
类型为
TEnumerable
的参数

例如,假设我们有
TDictionary
。然后我们可以将
TEnumerable
的一个实例传递给构造函数。这类事情的一个例子是

因此,如果您已经有一个字典实例,您可以创建另一个,并使用第一个实例的内容对其进行初始化:

Dict2 := TDictionary<string, Integer>.Create(Dict1);
Dict2:=TDictionary.Create(Dict1);

显然,您只需要一行程序,所以我尝试了一下,实现了一个
TDictHelper
,它允许使用一行程序创建和填充字典


使用任何形式的一行程序初始化字典的问题是它需要成对的值,而我们没有传递这些值对所需的良好语法。例如,如果需要为添加到字典中的每对值使用
TPair.Create(A,B)
语法,那么这将是一个难看的一行

我确实想出了几个好看的选择;第一个是这样使用的:

  with TDictHelper<Integer, string> do
    Dict := Make([P(1, 'one'), P(2, 'two')]);
这会管用,但会非常非常难看

由于将
一起使用可能会有问题(特别是如果您想使用两种词典),因此我提供了一种替代语法;不幸的是,这一个无法扩展,它很快变得非常丑陋:

  Dict := TDictHelper<Integer, string>.Make([1, 2], ['one', 'two']);

在下面的示例中,键和值的数组被传递给自定义构造函数。使用以下模式将键和值放置在同一数组中:key1、value1、key2、value2、…、keyN、valueN。数组必须包含偶数个项

unit MainUnit;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, System.Generics.Collections, System.Rtti;


type
  TForm3 = class(TForm)
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TMyDictionary<TK, TV> = class(TDictionary<TK,TV>)
    constructor Create(const values: array of variant);
  end;

var
  Form3: TForm3;
  extensions: TMyDictionary<string, integer>;

implementation

constructor TMyDictionary<TK, TV>.Create(const values: array of variant);
var
  I: Integer;
  k, v: TValue;
  kt: TK;
  vt: TV;
begin
  inherited Create(Length(values) div 2);
  I := Low(values);
  while i <= High(values)  do
  begin
    k := TValue.FromVariant(values[i]);
    v := TValue.FromVariant(values[i + 1]);
    kt := k.AsType<TK>;
    vt := v.AsType<TV>;
    Add(kt, vt);
    Inc(I, 2);
  end;

end;

{$R *.dfm}
begin

 extensions := TMyDictionary<string, integer>.Create(['1', 1, '3', 3]);

 OutputDebugString(PChar(IntToStr(extensions['1'])));
end.
单元主单元;
接口
使用
Winapi.Windows、Winapi.Messages、System.SysUtils、System.Variants、System.Classes、Vcl.Graphics、,
控件、窗体、对话框、System.Generics.Collections、System.Rtti;
类型
TForm3=类别(TForm)
私有的
{私有声明}
公众的
{公开声明}
结束;
TMyDictionary=类(TDictionary)
构造函数创建(常量值:变量数组);
结束;
变量
表3:TForm3;
扩展:TMyDictionary;
实施
构造函数TMyDictionary.Create(常量值:变量数组);
变量
I:整数;
k、 v:TValue;
kt:TK;
vt:电视;
开始
继承的Create(长度(值)div 2);
I:=低(值);

虽然我可能会感到困惑,但我认为:构造函数Create(Collection:TEnumerable);超载;他告诉我,在create方法期间,我可以用多对数据填充TDictionary。我是否误读了符号?只有两个构造函数重载允许您在构造期间填充。它们都接收类型为
TEnumerable
的类的实例。您可以编写一个helper函数来创建一个允许内联编码的函数。它与Python版本有很长的距离:
Dictionary={'Foo':42,'Bar':666}
实际上,您甚至不能在这里编写帮助函数,因为您需要释放传递给构造函数的临时容器。所以,是的,这个班级的设计是反对你的。在这种情况下,其他一些容器库可能更灵活。我不知道,但我听到了很多关于Delphi spring库中容器的好消息。@David太糟糕了,它不需要一个
IEnumerable
@David,正如我的回答所示,一个开放的成对数组很难以可读的方式实例化。这就是为什么我使用
with
操作符,所以我可以使用helper
P
类函数。Delphi中没有语法可以用一行程序来初始化记录,你需要调用一个构造函数。请注意,它从来不会精确地执行问题所要求的操作,即在其构造函数中填充dict。无论如何,当dict构造函数使用TEnumerable执行此操作时,它会调用AddOrSetValue,您可能希望在这里进行模拟。@David,我把这个问题看作是在询问一种填充
TDictionary
的单行程序方法。当然,我可能错了。不,这很公平。我很高兴有一点创造性的解释。我的回答是直截了当的。你的值+1。
Dict := TDictHelper<Integer, string>.Make(TPair<Integer, string>.Create(1, 'one'), TPair<Integer, string>.Create(2, 'two'));
  Dict := TDictHelper<Integer, string>.Make([1, 2], ['one', 'two']);
program Project25;

{$APPTYPE CONSOLE}

uses
  SysUtils, Generics.Collections;

type
  TDictHelper<Key, Value> = class
  public
    class function P(const K:Key; const V:Value): TPair<Key, Value>;
    class function Make(init: array of TPair<Key, Value>): TDictionary<Key, Value>;overload;
    class function Make(KeyArray: array of Key; ValueArray: array of Value): TDictionary<Key, Value>;overload;
  end;

{ TDictHelper<Key, Value> }

class function TDictHelper<Key, Value>.Make(init: array of TPair<Key, Value>): TDictionary<Key, Value>;
var P: TPair<Key, Value>;
begin
  Result := TDictionary<Key, Value>.Create;
  for P in init do
    Result.AddOrSetValue(P.Key, P.Value);
end;

class function TDictHelper<Key, Value>.Make(KeyArray: array of Key;
  ValueArray: array of Value): TDictionary<Key, Value>;
var i:Integer;
begin
  if Length(KeyArray) <> Length(ValueArray) then
    raise Exception.Create('Number of keys does not match number of values.');
  Result := TDictionary<Key, Value>.Create;
  for i:=0 to High(KeyArray) do
    Result.AddOrSetValue(KeyArray[i], ValueArray[i]);
end;

class function TDictHelper<Key, Value>.P(const K: Key;
  const V: Value): TPair<Key, Value>;
begin
  Result := TPair<Key, Value>.Create(K, V);
end;

// ============================== TEST CODE FOLLOWS

var Dict: TDictionary<Integer, string>;
    Pair: TPair<Integer, string>;

begin
  try
    try
      // Nice-looking but requires "with" and you can't work with two kinds of DictHelper at once
      with TDictHelper<Integer, string> do
        Dict := Make([P(1, 'one'), P(2, 'two')]);
      // Use the array
      for Pair in Dict do
        WriteLn(Pair.Key, ' = ', Pair.Value);
      Dict.Free;

      // Passing the Keys and the Values in separate arrays; Works without "with" but it would
      // be difficult to maintain for larger number of key/value pairs
      Dict := TDictHelper<Integer, string>.Make([1, 2], ['one', 'two']);
      // Use the array
      for Pair in Dict do
        WriteLn(Pair.Key, ' = ', Pair.Value);
      Dict.Free;

    except on E:Exception do
      WriteLn(E.ClassName, #13#10, E.Message);
    end;
  finally ReadLn;
  end;
end.
unit MainUnit;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, System.Generics.Collections, System.Rtti;


type
  TForm3 = class(TForm)
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TMyDictionary<TK, TV> = class(TDictionary<TK,TV>)
    constructor Create(const values: array of variant);
  end;

var
  Form3: TForm3;
  extensions: TMyDictionary<string, integer>;

implementation

constructor TMyDictionary<TK, TV>.Create(const values: array of variant);
var
  I: Integer;
  k, v: TValue;
  kt: TK;
  vt: TV;
begin
  inherited Create(Length(values) div 2);
  I := Low(values);
  while i <= High(values)  do
  begin
    k := TValue.FromVariant(values[i]);
    v := TValue.FromVariant(values[i + 1]);
    kt := k.AsType<TK>;
    vt := v.AsType<TV>;
    Add(kt, vt);
    Inc(I, 2);
  end;

end;

{$R *.dfm}
begin

 extensions := TMyDictionary<string, integer>.Create(['1', 1, '3', 3]);

 OutputDebugString(PChar(IntToStr(extensions['1'])));
end.