2013-01-11 83 views
3

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

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

+0

请你能编辑你的问题更清楚。对不起,我不明白你想做什么。第三和第四名单呢? – Zeina

+0

我会尝试,但很难 – Craig

+1

你应该简单地发布shuffle前后列表的示例内容 –

回答

3

我打算考虑你有两个列表的情况。我将留给你来概括这些想法来处理两个以上的列表。关键的理解最好使用最简单的情况获得,其中有两个列表。

我想解决这样的问题:

  1. 生成整数0,1,...,N-1的排列。使用Fisher–Yates shuffle来实现这一点。
  2. 使用该排列混洗两个列表。

关键是使用相同的置换来洗牌两个列表。

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; 

我竭力想一个好名字这个程序。任何人都可以通过提供更好的东西来帮助我?

+0

+1作为对此的扩展,您可以使用包含TStringList的动态数组构建过程。但基本显示​​ –

+0

SynchronListPermutation –