(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)
Shuffle order of cell array without repeating rows
10 次查看(过去 30 天)
显示 更早的评论
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?
采纳的回答
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
A(idx)
0 个评论
更多回答(1 个)
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)
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
0 个评论
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Characters and Strings 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!