随机化多个Stringlists

时间:2013-01-11 10:00:55

标签: delphi random delphi-7

我想随机化一些字符串列表。

字符串列表包含相同数量的项目,我希望对每个列表应用相同的shuffle。因此,如果List1[0]List1[7]交换,那么我想将List2[0]List2[7]交换,依此类推所有列表。

1 个答案:

答案 0 :(得分:3)

我将考虑你有两个名单的情况。我将由您来概括处理两个以上列表的想法。使用最简单的情况可以获得关键的理解,其中有两个列表。

我会解决这个问题:

  1. 生成整数0,1,... N-1的排列。使用Fisher–Yates shuffle来实现此目的。
  2. 使用该排列来混洗这两个列表。
  3. 关键是使用相同的排列来混洗两个列表。

    type
      TIntegerArray = array of Integer;
    
    procedure Swap(var i1, i2: Integer); overload;
    var
      tmp: Integer;
    begin
      tmp := i1;
      i1 := i2;
      i2 := tmp;
    end;
    
    function GeneratePermutation(Count: Integer): TIntegerArray;
    //Fisher-Yates shuffle
    var
      i, j: Integer;
    begin
      SetLength(Result, Count);
      for i := 0 to Count-1 do
        Result[i] := i;
      for i := Count-1 downto 1 do begin
        j := Random(i+1);
        Swap(Result[i], Result[j]);
      end;
    end;
    
    procedure ApplyPermutation(List: TStringList; 
      const Permutation: TIntegerArray);
    var
      i: Integer;
      Temp: TStringList;
    begin
      Assert(List.Count=Length(Permutation));
      Temp := TStringList.Create;
      try
        Temp.Assign(List);
        for i := 0 to List.Count-1 do
          List[i] := Temp[Permutation[i]];
      finally
        Temp.Free;
      end;
    end;
    

    然后你可以适用于你的情况:

    Permutation := GeneratePermutation(List1.Count);
    Apply(List1, Permutation);
    Apply(List2, Permutation);
    

    这是一个非常通用的解决方案,可以扩展到两个以上的列表,并且可以应用于其他数据类型。如果你想要一个非常简短的专用例程,那么你可以这样做:

    procedure PermuteListsInTandem(List1, List2: TStringList);
    var
      i, j: Integer;
    begin
      Assert(List1.Count=List2.Count);
      for i := List1.Count-1 downto 1 do begin
        j := Random(i+1);
        List1.Exchange(i, j);
        List2.Exchange(i, j);
      end;
    end;
    

    我很难想到这个程序的好名字。任何人都可以通过提供更好的东西帮助我吗?