2015-03-23 4 views
2

У меня есть массив A = [1,2] и B = [5,6]
Я хочу сгенерировать массив C = [1 * 1,2 * 2,5 * 5,6 * 6,1 * 2,1 * 5,1 * 6,2 * 5,2 * 6,5 * 6]
Это все возможные комбинации (a b равно b a и, следовательно, только 1 из них должен быть на результирующем массиве C).Эффективный способ генерации всех возможных комбинаций элементов в 2 массивах

Есть ли встроенная функция Matlab, которую я могу использовать для достижения этой цели?
Вы можете мне помочь?

+1

Что делать, если у вас есть A = [2,4] B = [3,6] - должно появляться два раза (3 * 4,6 * 2) или только один раз? – amit

+0

Как работает * 2 массива * здесь? Кажется, не имеет значения, какие элементы находятся в массиве. Он должен быть таким же, как выбор двух элементов из '[A, B]'. – knedlsepp

ответ

3

Здесь могут быть предложены два подхода с bsxfun.

Подход # 1

%// Form a concatenated array 
AB = [A(:) ; B(:)] 

%// Get pairwise multiplications between all elements 
allvals = bsxfun(@times,AB,AB.') %//' 

%// Discard the repeated ones for the final output 
C = allvals(bsxfun(@le,[1:numel(AB)]',1:numel(AB))) 

Подход № 2

%// Form a concatenated array 
AB = [A(:) ; B(:)] 

%// Get "non-repeated" pairwise indices 
[Y,X] = find(bsxfun(@le,[1:numel(AB)]',1:numel(AB))) %//' 

%// Elementwise multiplications across all such pairs for final output 
C = AB(X).*AB(Y) 

Второй основан на Fastest solution to list all pairs of n integers и меньше памяти по сравнению с первым подходом.

1

Попробуйте следующий код:

%merge 
AB = [A(:) ; B(:)] 
%multiply to get all combinations 
C=AB*AB' 
%delete everything below the first diagonal 
C=C(triu(true(numel(AB)))); 
2

Альтернативой является использование pdist (из Statistics Toolbox) с анонимной функцией:

AB = [A(:); B(:)]; 
C = [AB.'.^2 pdist(AB, @(x,y) x*y)]; 
+0

Хорошее мышление об этом! Сделали некоторые быстрые тесты, и этот самый быстрый для действительно больших массивов! – Divakar

+0

@ Divakar Спасибо! В последних версиях Matlab 'pdist' использует mex-файл для выполнения фактических вычислений; это должно быть (частью) причины –

+1

Ну, в моих тестах утверждается, что мой подход # 1 'bsxfun' работает очень хорошо, пока numel (A) не будет' 2000', то есть numel (AB) - '4000', после чего я угадываю тяжелые требования к памяти 'bsxfun' запускаются, а затем' pdist' начинает светиться после этого. Не видя ясного победителя! – Divakar

0

Это не добавляет много к вопросу, который вы используете два вектора. Вы просто хотите, чтобы продукт каждой комбинации n choose 2 составлял конкатенацию x = [A(:); B(:)].

prod(x(nchoosek(1:numel(x), 2)), 2) 
Смежные вопросы