我正在 Matlab Psychtoolbox 中编写一个实验,我的条件存储在这样的数组中
Cond = ["VM" "VM" "VN" "VS" "AM" "AM" "AN" "AS" "CM" "CM" "CN" "CS"...
"VM" "VM" "VN" "VS" "AM" "AM" "AN" "AS" "CM" "CM" "CN" "CS"];
我现在想以一种没有重复条件的方式对数组进行洗牌。
关于这个问题有很多治疗方法,例如this one ,但他们总是同样频繁地出现每种情况。
一些人建议采用蛮力方法,经常进行洗牌,直到达到这个标准。但由于我有这个条件数组的树,并且每次实验运行都必须将它们洗牌几次,我认为这不是一个好的解决方案。
希望有人能帮忙
最佳答案
我设计了一种算法,应该可以满足您的要求。给定一个序列,它会随机重新排序,这样就不会出现重复的值。然而,它似乎确实有创建重复子序列的倾向(例如...“A”“B”“C”“A”“B”“C”...
)。我将它包装在函数 reorder_no_reps
中:
function seq = reorder_no_reps(seq)
% Find unique values and counts:
N = numel(seq);
[vals, ~, index] = unique(seq(:), 'stable');
counts = accumarray(index, 1);
[maxCount, maxIndex] = max(counts);
% Check the maximum number of occurrences:
if (2*maxCount-1 > N)
error('Can''t produce sequence without repeats!');
end
% Fill cell array column-wise with permuted and replicated set of values:
C = cell(maxCount, ceil(N/maxCount));
if (3*maxCount-1 > N)
permIndex = [maxIndex(1) ...
setdiff(randperm(numel(vals)), maxIndex(1), 'stable')];
else
permIndex = randperm(numel(vals));
end
C(1:N) = num2cell(repelem(vals(permIndex), counts(permIndex)));
% Transpose cell array and extract non-empty entries:
C = C.';
seq = reshape([C{~cellfun('isempty', C)}], size(seq));
end
算法步骤的描述:
- 查找输入序列中的唯一值 (
vals
) 以及它们各自出现的次数 (counts
)。 - 查找单个值的最大出现次数 (
maxCounts
),并检查它是否太大而无法构成不重复的序列。 - 随机排列顺序应用于唯一值及其计数。如果最大出现次数超过给定阈值,则相应的值索引将移至随机顺序的开头(下一个项目符号中将说明原因)。
- 然后,每个唯一值将按照其在序列中出现的次数进行适当复制。元胞数组按列顺序填充这些复制的值,可能会在末尾留下一些单元格为空。由于元胞数组的行数等于某个值的最大出现次数,因此生成的元胞数组的单行中不会出现多次出现的值。此外,每行中的最后一个值应与后续行中的第一个值不同(通过在某些情况下首先填充最常出现的值来确保)。
- 转置元胞数组,然后按列顺序拉取所有非空元胞值,并将它们重新调整为与输入序列相同的大小。这与从非转置元胞数组中按行提取值相同,这应该为您提供一个没有重复值的序列。
关于arrays - 打乱一组不均匀重复的条目,使它们不重复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57509620/