Shuffle order of cell array without repeating rows

조회 수: 31 (최근 30일)
Michael
Michael 2023년 10월 4일
답변: Bruno Luong 2023년 10월 4일
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
Michael
Michael 2023년 10월 4일
(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)

댓글을 달려면 로그인하십시오.

채택된 답변

Dyuman Joshi
Dyuman Joshi 2023년 10월 4일
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"]}

추가 답변 (1개)

Bruno Luong
Bruno Luong 2023년 10월 4일
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

카테고리

Help CenterFile Exchange에서 Characters and Strings에 대해 자세히 알아보기

제품


릴리스

R2023b

Community Treasure Hunt

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

Start Hunting!

Translated by