Я хотел бы сгенерировать все возможные комбинации элементов заданного числа векторов.
Например, для [1 2]
, [1 2]
и [4 5]
я хочу сгенерировать элементы:
[1 1 4; 1 1 5; 1 2 4; 1 2 5; 2 1 4; 2 1 5; 2 2 4; 2 2 5]
Проблема в том, что я не знаю числа векторов, для которых мне нужно вычислить комбинации. В этом случае может быть 3, или может быть 10, и мне нужно обобщение. Не могли бы вы помочь мне в этом в MATLAB? Есть ли уже предопределенная функция, которая может выполнить эту задачу?
Попробуйте ALLCOMB в FileExchange.
Если вы храните векторы в массиве ячеек, вы можете запустить его следующим образом:
a = {[1 2], [1 2], [4 5]};
allcomb(a{:})
ans =
1 1 4
1 1 5
1 2 4
1 2 5
2 1 4
2 1 5
2 2 4
2 2 5
ALLCOMB
использует NDGRID
по существу так же, как в ответе Амро, с NDGRID
от ошибок сверху.
Рассмотрим это решение, используя функцию NDGRID:
sets = {[1 2], [1 2], [4 5]};
[x y z] = ndgrid(sets{:});
cartProd = [x(:) y(:) z(:)];
cartProd =
1 1 4
2 1 4
1 2 4
2 2 4
1 1 5
2 1 5
1 2 5
2 2 5
Или, если вы хотите общее решение для любого количества наборов (без необходимости создавать переменные вручную), используйте это определение функции:
function result = cartesianProduct(sets)
c = cell(1, numel(sets));
[c{:}] = ndgrid( sets{:} );
result = cell2mat( cellfun(@(v)v(:), c, 'UniformOutput',false) );
end
Обратите внимание: если вы предпочитаете, вы можете отсортировать результаты:
cartProd = sortrows(cartProd, 1:numel(sets));
Кроме того, приведенный выше код не проверяет, нет ли у наборов повторяющихся значений (например: {[1 1] [1 2] [4 5]}
). Добавьте эту строку, если хотите:
sets = cellfun(@unique, sets, 'UniformOutput',false);
Эти поздние ответы предоставляют два дополнительных решения, где второе решение (на мой взгляд) и улучшение решения ответа Amro с помощью ndgrid
путем применения мощных списков разделенных запятыми MATLAB вместо массивов ячеек для высокой производительности,
combvec
Как и Амро в своем ответе, синтаксис списков, разделенных запятыми (v{:}
), снабжает входы и выходы ndgrid
. Разница (четвертая строка) заключается в том, что она избегает cellfun
и cell2mat
, применяя списки, разделенные запятыми, снова, теперь как входы для cat
:
N = numel(a);
v = cell(N,1);
[v{:}] = ndgrid(a{:});
res = reshape(cat(N+1,v{:}),[],N);
Использование cat
и reshape
сокращает время выполнения почти вдвое. Этот подход был продемонстрирован в моем ответе на другой вопрос и более формально Луисом Мендо.
мы также можем использовать инструкцию combvec в matlab
no_inp=3 % number of inputs we want...in this case we have 3 inputs
a=[1 2 3]
b=[1 2 3]
c=[1 2 3]
pre_final=combvec(c,b,a)';
final=zeros(size(pre_final));
for i=1:no_inp
final(:,i)=pre_final(:,no_inp-i+1);
end
final
Надеюсь, это поможет. Удачи.