I want to randomize a number of string lists.
The string lists all contain the same number of items, and I wish to apply the same shuffle to each list. So if List1[0] is swapped with List1[7], then I want to swap List2[0] with List2[7], and so on for all the lists.
I'm going to consider the case where you have two lists. I'll leave it up to you to generalise the ideas to handle more than two lists. The key understanding is best gained using the most simple case where there are two lists.
I would solve the problem like this:
The key is to use the same permutation to shuffle both lists.
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;
And then you can apply to your situation like this:
Permutation := GeneratePermutation(List1.Count);
Apply(List1, Permutation);
Apply(List2, Permutation);
This is an exceedingly general solution that can be extended to more than two lists, and can be applied to other data types. If you want a very short and simple dedicated routine then you can do it like this:
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;
I'm struggling to think of a good name for this procedure. Can anyone help me out by offering something better?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With