Shuffle order of cell array without repeating rows

11 Ansichten (letzte 30 Tage)
Michael
Michael am 4 Okt. 2023
Beantwortet: Bruno Luong am 4 Okt. 2023
I have a cell array of duplicated strings (filenames, in my application) the order of which I would like to pseudo-randomise, such that it is shuffled but without having repeated neighbouring entries.
For example, I can get a completely randomised ordering by using...
A = {"string1"; "string2"; "string3"; "string1"; "string2"; "string3"; "string1"; "string2"; "string3"; "string1"; "string2"; "string3"};
A = A(randperm(size(A, 1)), :)
...but this will often result in some entries repeating in adjacent rows, eg:
{["string2"]}
{["string3"]}
{["string2"]}
{["string2"]}
{["string2"]}
{["string3"]}
{["string1"]}
{["string3"]}
{["string3"]}
{["string1"]}
{["string1"]}
{["string1"]}
Is there a way I can ensure each row entry is always different to both its adjacent rows? Eg:
{["string3"]}
{["string1"]}
{["string2"]}
{["string1"]}
{["string2"]}
{["string3"]}
{["string1"]}
{["string2"]}
{["string1"]}
{["string3"]}
{["string2"]}
{["string3"]}
I guess I could use a while loop to keep randomising, but how would I terminate that loop by checking if the output is pseudo-random in the desired way?
  1 Kommentar
Michael
Michael am 4 Okt. 2023
(I realise I don't need to use 'size' here, but in my application my array has multiple columns - I only want to randomise the row ordering)

Melden Sie sich an, um zu kommentieren.

Akzeptierte Antwort

Dyuman Joshi
Dyuman Joshi am 4 Okt. 2023
A brute force approach tailored to the example you have posted -
A = {"string1"; "string2"; "string3"; "string1"; "string2"; "string3"; "string1"; "string2"; "string3"; "string1"; "string2"; "string3"};
s = size(A,1);
r = numel(unique([A{:}]));
idx = randperm(s);
while any(diff(rem(idx,r))==0)
idx = randperm(s);
end
idx
idx = 1×12
11 9 1 2 6 10 5 12 7 8 4 3
A(idx)
ans = 12×1 cell array
{["string2"]} {["string3"]} {["string1"]} {["string2"]} {["string3"]} {["string1"]} {["string2"]} {["string3"]} {["string1"]} {["string2"]} {["string1"]} {["string3"]}

Weitere Antworten (1)

Bruno Luong
Bruno Luong am 4 Okt. 2023
This does not require any special structure of the input (such as number of elements; or groups, or cardinal of groups, or the order)
% I change to string array rather than cell of strings
list = ["string2"
"string3"
"string2"
"string2"
"string2"
"string3"
"string1"
"string3"
"string4"
"string1"
"string1"
"string1"
"string1"
"string2"];
randperm_nrc(list)
ans = 14×1 string array
"string4" "string2" "string1" "string2" "string3" "string1" "string2" "string1" "string3" "string1" "string2" "string3" "string2" "string1"
function listperm = randperm_nrc(list)
n = length(list);
[u,~,J]=unique(list);
cref = accumarray(J,1);
succeed = false;
while ~succeed
c = cref;
y = zeros(1,n);
x = [];
for i = 1:n
cn = c;
cn(x) = 0;
cc = cumsum(cn);
s = cc(end);
succeed = s > 0;
if ~succeed
break
end
x = discretize(rand(), [0; cc/s]);
c(x) = c(x)-1;
y(i) = x;
end
end
listperm = u(y);
end

Kategorien

Mehr zu Characters and Strings finden Sie in Help Center und File Exchange

Produkte


Version

R2023b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by