按阵列或列表中的GroupID对元素进行分组?

时间:2013-11-12 13:16:02

标签: delphi delphi-7 grouping

我做了一个简化的演示(带有伪结构)来说明我需要的东西:

type
  TMyRec = record
    GroupID: Integer;
    Color: TColor;
  end;

  TMyRecArray = array of TMyRec;

我的输入数组/列表元素由非零GroupID组成。它们始终按GroupID分组(但未排序且无法排序):

GroupID
-------
2 
2
2
1
1
3
3
etc...

每个元素都有一个Color。我的输出应按GroupID分组,看起来像这样(每个组都是clRed / clGreen - 轮流交替):

GroupID ; Color
-------   -----
2 ; clRed
2 ; clRed
2 ; clRed
1 ; clGreen
1 ; clGreen
3 ; clRed
3 ; clRed
etc...
9 ; clGreen    
7 ; clRed
7 ; clRed    

我使用代码:

procedure TForm1.Button1Click(Sender: TObject);
var
  R: TMyRecArray;
  I: Integer;
  S: string;
  OldId: Integer;
begin
  // populate some data
  SetLength(R, 7);
  R[0].GroupID := 2;
  R[1].GroupID := 2;
  R[2].GroupID := 2;
  R[3].GroupID := 1;
  R[4].GroupID := 1;
  R[5].GroupID := 3;
  R[6].GroupID := 3;

  OldId := 0;
  for I := 0 to High(R) do
  begin
    if OldId <> R[I].GroupID then
    begin
      OldId := R[I].GroupID;
      R[I].Color := clRed;
    end
    else
    begin
      R[I].Color := clGreen;
    end;
  end;

  Memo1.Clear;
  for I := 0 to High(R) do
  begin
    ColorToIdent(R[I].Color, S);
    Memo1.Lines.Add(Format('%d ; %s', [R[I].GroupID, S]));
  end;
end;

结果是正确:

2 ; clRed
2 ; clGreen
2 ; clGreen
1 ; clRed
1 ; clGreen
3 ; clRed
3 ; clGreen

我错过了什么?我知道解决方案很简单但我无法理解它。
限制:我只能迭代一次;我无法提前阅读/以前的记录。

1 个答案:

答案 0 :(得分:7)

“分而治之。”您可以从决策中分离属性的收集和应用着色。

  OldId := 0; GroupNo := 0;
  for I := Low(R) to High(R) do
  begin
    if (OldId <> R[I].GroupId) or (GroupNo = 0) then
    begin
      OldId := R[I].GroupId;
      Inc(GroupNo);
      ItemNo := 0;
    end;
    Inc(ItemNo); 

    R[I].Color := GroupColor(OldId, GroupNo, ItemNo);
  end;

然后,您可以专注于选择本身,而不会满足于实际着色,数据迭代等细节。这也可以让您更灵活地实际需要什么。 GroupColor甚至可以是变量,根据设置实现不同的突出显示模式。

您想要在群组后交替颜色分组吗?

  function GroupColor(const Id, Number, Item: integer): TColor;
  begin
    if Odd(Number) 
       then Result := clRed
       else Result := clGreen
  end;

或者您希望不同的群体有不同的颜色?

  function GroupColor(const Id, Number, Item: integer): TColor;
  begin
    case Id of
       1: Result := clRed;
       2: Result := clYellow;
       3: Result := clBlue;
       4: Result := clGreen;
       else Result := clWhite;
    end;
  end;

或者你是否想要强调每个群体的领导者?

  function GroupColor(const Id, Number, Item: integer): TColor;
  begin
    case Item of
       1: Result := clRed;
       2: Result := clYellow;
       3: Result := clGreen;
       else Result := clGray;
    end;
  end;