Delphi标签值排序

发布于 2024-11-27 02:36:17 字数 463 浏览 0 评论 0原文

我正在尝试对标签的值进行排序。我有很多带有整数值的标签。标签的名称如 Label1、Label2、[...],我通过 FindComponent 访问它们。我对存储在数组中的整数值进行排序没有问题,但问题是,排序后,我不知道哪个标签有什么值。我的目标是喜欢按标签的值对这些标签进行排序,因此我会得到一个标签按其值排序的数组。我被困在这一点上:( 例如:

Label1.Caption := 10;
Label2.Caption := 4;
Label3.Caption := 7;

for i := 1 to 3
 do some_array[i] := StrToInt(TLabel(FindComponent('Label' + IntToStr(i))).Caption);

sortarray(some_array);

现在,我已经对数组进行了排序,但是我缺少一些排序程序,该程序也可以将标签号存储在相应的位置。有人可以指出我吗?

Im trying to sort Label's values. I have lots of labels with an integer value. Labels are called like Label1, Label2, [...], which Im accessing through FindComponent. I have no problem in sorting the integer values Ive stored in an array, but the problem is, after sorting, I have no idea which label had what value. My goal is to like, sort those labels by their value, so I'd get like an array with Labels sorted by their value. Im stuck at this point :(
Eg:

Label1.Caption := 10;
Label2.Caption := 4;
Label3.Caption := 7;

for i := 1 to 3
 do some_array[i] := StrToInt(TLabel(FindComponent('Label' + IntToStr(i))).Caption);

sortarray(some_array);

Now, I have sorted array, but Im lacking some sort procedure that would also store label number in the corresponding place. Can someone point me out?

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

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

发布评论

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

评论(4

岁月打碎记忆 2024-12-04 02:36:17

创建一个 TLabel 控件数组,而不是创建一个整数数组。您可以按照与整数数组相同的方式对这个数组进行排序。事实上,给定一个 MyLabel: TLabel,您可以轻松获取关联的整数,如 StrToInt(MyLabel.Caption)

此外,FindComponent 方法的效率不是很高。当然

const
  ALLOC_BY = 100;
  MAGIC_TAG = 871226;
var
  i: Integer;
  ActualLength: integer;
  FLabels: array of TLabel;
begin
  SetLength(FLabels, ALLOC_BY);
  ActualLength := 0;
  for i := 0 to ControlCount - 1 do
    if Controls[i] is TLabel then
      with TLabel(Controls[i]) do
        if Tag = MAGIC_TAG then
        begin
          if ActualLength = length(FLabels) then
            SetLength(FLabels, length(FLabels) + ALLOC_BY);
          FLabels[ActualLength] := Controls[i];
          inc(ActualLength);
        end;
  SetLength(FLabels, ActualLength);

  SortArray(FLabels) // with respect to the StrToInt(CurLabel.Caption) of each
                     // CurLabel: TLabel.

,如果您提前知道标签的数量,您可以跳过块分配。

确保要包含在数组中的每个标签的 Tag 设置为 MAGIC_TAG

另一种选择是创建一个

FLabelDataArray: array of  TLabelData;

type
  TLabelData = record
    Control: TLabel;
    Value: integer;
  end;

数组。

FLabelDataArray[i].Value := StrToInt(FLabelDataArray[i].Control.Caption);

仅计算一次

Instead of creating an array of integers, create an array of TLabel controls. This one you can sort the same way as the array of integers. Indeed, given a MyLabel: TLabel, you can easily get the associated integer as StrToInt(MyLabel.Caption).

In addition, the FindComponent approach is not very efficient. I'd do

const
  ALLOC_BY = 100;
  MAGIC_TAG = 871226;
var
  i: Integer;
  ActualLength: integer;
  FLabels: array of TLabel;
begin
  SetLength(FLabels, ALLOC_BY);
  ActualLength := 0;
  for i := 0 to ControlCount - 1 do
    if Controls[i] is TLabel then
      with TLabel(Controls[i]) do
        if Tag = MAGIC_TAG then
        begin
          if ActualLength = length(FLabels) then
            SetLength(FLabels, length(FLabels) + ALLOC_BY);
          FLabels[ActualLength] := Controls[i];
          inc(ActualLength);
        end;
  SetLength(FLabels, ActualLength);

  SortArray(FLabels) // with respect to the StrToInt(CurLabel.Caption) of each
                     // CurLabel: TLabel.

Of course, you can skip the chunk allocating if you know the number of labels in advance.

Make sure that each of the labels that are to be included in the array have the Tag set to MAGIC_TAG.

Another option would be to create an array

FLabelDataArray: array of  TLabelData;

of

type
  TLabelData = record
    Control: TLabel;
    Value: integer;
  end;

where

FLabelDataArray[i].Value := StrToInt(FLabelDataArray[i].Control.Caption);

is computed only once.

惜醉颜 2024-12-04 02:36:17

一个快速但肮脏的解决方案也适用于旧的 Delphi 版本,那就是使用 TStringList,它有一个 Sort 方法和一个 Objects 属性允许您将一个对象与列表中的每个条目相关联。

请注意,列表按字典顺序排序,因此在转换为字符串时必须用零填充整数。

var
  list: TStringList;
  i: integer;
  lab: TLabel;
begin
  Label1.Caption := '10';
  Label2.Caption := '4';
  Label3.Caption := '7';

  list := TStringList.Create;
  try
    for i := 1 to 3 do begin
      lab := TLabel(FindComponent('Label' + IntToStr(i)));
      list.AddObject(Format('%10.10d', [StrToInt(lab.Caption)]), lab);
    end;

    list.Sort;

    for i := 0 to list.Count-1 do
      Memo1.Lines.Add(list[i] + #9 + TLabel(list.Objects[i]).Name);
  finally
    list.Free;
  end;
end;

输出将是:

0000000004   Label2
0000000007   Label3
0000000010   Label1

另外,如果您使用 list.Sorted := true 而不是 list.Sort,您将在 list 上进行二分搜索:奖励(使用list.IndexOflist.Find)。

编辑:正如Rudy所说,诸如TLabel之类的可视化组件应该只用于显示数据,而不是用于存储和操作数据。建议为此使用适当的数据结构,并将程序逻辑与其用户界面分开。

A quick-n-dirty solution that also works in old Delphi versions, is to use TStringList, which has a Sort method and an Objects property that allow you to associate one object to each entry in the list.

Note that the list is sorted in lexicographic order, so the integers must be left padded with zeroes when converted to strings.

var
  list: TStringList;
  i: integer;
  lab: TLabel;
begin
  Label1.Caption := '10';
  Label2.Caption := '4';
  Label3.Caption := '7';

  list := TStringList.Create;
  try
    for i := 1 to 3 do begin
      lab := TLabel(FindComponent('Label' + IntToStr(i)));
      list.AddObject(Format('%10.10d', [StrToInt(lab.Caption)]), lab);
    end;

    list.Sort;

    for i := 0 to list.Count-1 do
      Memo1.Lines.Add(list[i] + #9 + TLabel(list.Objects[i]).Name);
  finally
    list.Free;
  end;
end;

The output would be:

0000000004   Label2
0000000007   Label3
0000000010   Label1

Also, if instead of list.Sort you use list.Sorted := true, you get binary search on list as a bonus (using list.IndexOf or list.Find).

Edit: As Rudy says, visual components such as TLabel should only be used for displaying data, and not for storing and manipulating it. It is recommended to use appropiate data structures for this and to separate the logic of the program from its user interface.

咿呀咿呀哟 2024-12-04 02:36:17

正如 Andreas 所说,将标签放入动态数组中,而不是对值进行排序。一旦将它们放入这样的数组中,请像这样对它们进行排序:

uses
  Generics.Defaults, Generics.Collections;

procedure SortLabels(var Labels: array of TLabel);
var
  Comparison: TComparison<TLabel>;
  Comparer: IComparer<TLabel>;
begin
  Comparison := function(const Left, Right: TLabel): Integer
    begin
      Result := StrToInt(Left.Caption)-StrToInt(Right.Caption);
    end;
  Comparer := TDelegatedComparer<TLabel>.Create(Comparison);
  TArray.Sort<TLabel>(Labels, Comparer);
end;

As Andreas says, put the labels into a dynamic array, rather than sorting the values. Once you have them in such an array, sort them like this:

uses
  Generics.Defaults, Generics.Collections;

procedure SortLabels(var Labels: array of TLabel);
var
  Comparison: TComparison<TLabel>;
  Comparer: IComparer<TLabel>;
begin
  Comparison := function(const Left, Right: TLabel): Integer
    begin
      Result := StrToInt(Left.Caption)-StrToInt(Right.Caption);
    end;
  Comparer := TDelegatedComparer<TLabel>.Create(Comparison);
  TArray.Sort<TLabel>(Labels, Comparer);
end;
中性美 2024-12-04 02:36:17

正如其他人所说,我认为您没有采取正确的方法来完成这项任务。但是,根据您的问题,一个简单的技巧是使用每个标签上的 tag 属性来存储其标题的值:

Label1.Caption := '10';
Label1.Tag:=10;
Label2.Caption := '4';
Label2.Tag:=4;
Label3.Caption := '7';
Label3.Tag := 7;

然后您可以通过将“整数数组”条目与标签的 tag 属性相匹配来找到适当的标签。

再次:正如 Rudy 和其他人评论的那样,您完成此任务的方法远非理想,而我的解决方案仅符合您的方法。 tag 属性本身是 Delphi 中内置的一个 hack,是一个来自古代的神器,就像“label”和“goTo”一样,除非出于纯粹的绝望,否则真的不应该使用 - 就像当试图重新工作和改造古代时,代码写得不好,或者如果您有产品中的某些东西,并且您必须快速修复紧急情况。

As others have said, I don't think you're taking the right approach for this task. But, based on your question, a simple hack would be to use the tag property on each label to store its caption's value :

Label1.Caption := '10';
Label1.Tag:=10;
Label2.Caption := '4';
Label2.Tag:=4;
Label3.Caption := '7';
Label3.Tag := 7;

Then you can find the appropriate label by matching the 'array of integer' entry with the label's tag property.

Again: As Rudy and others have commented, your approach to this task is far from desirable, and my solution only conforms to your approach. The tag property itself is a hack built into Delphi, an artifact from ancient times, like 'label' and 'goTo' and really should not be used except out of sheer desperation - like when trying to re-work and retro-fit ancient, poorly written code or if you've got something in prod and you must get in a quick fix for an emergency situation.

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