我想随机化一些字符串列表。
字符串列表包含相同数量的项目,我希望对每个列表应用相同的shuffle。因此,如果List1[0]
与List1[7]
交换,那么我想将List2[0]
与List2[7]
交换,依此类推所有列表。
答案 0 :(得分: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;
我很难想到这个程序的好名字。任何人都可以通过提供更好的东西帮助我吗?