Мне не раз приходилось генерировать все возможные пары двух векторов в MATLAB, которые я делаю для циклов, которые занимают несколько строк кода i.e.
vec1 = 1:4;
vec2 = 1:3;
i = 0;
pairs = zeros([4*3 2]);
for val1 = vec1
for val2 = vec2
i = i + 1;
pairs(i,1) = val1;
pairs(i,2) = val2;
end
end
Создает...
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
4 1
4 2
4 3
Должен быть лучший способ сделать это, что больше MATLAB'esque?
n.b. nchoosek
не выполняет обратные пары, которые мне нужны (т.е. 2 1
, а также 1 2
), я не могу просто отменить и добавить вывод nchoosek
, потому что симметричные пары будут включены дважды.
Try
[p,q] = meshgrid(vec1, vec2);
pairs = [p(:) q(:)];
См. документацию MESHGRID. Хотя это не совсем то, для чего предназначена эта функция, но если вы прищурились, что то, о чем вы просите, это именно то, что она делает.
meshgrid
и сериализацию 2d векторов, но никогда не думал об их использовании таким образом.
Вы можете использовать
a = 1:4;
b = 1:3;
result = combvec(a,b);
result = result'
Другое решение для коллекции:
[idx2, idx1] = find(true(numel(vec2),numel(vec1)));
pairs = [reshape(vec1(idx1), [], 1), reshape(vec2(idx2), [], 1)];
vec1
vec2
исправить это, чтобы получить комбинации vec1
и vec2
.
find
всегда должны быть векторами столбцов, а также vec1(idx1)
и т. Д.
Вы можете сделать это, реплицируя матрицы с помощью repmat
, а затем превратив результат в вектор-столбец с помощью reshape
.
a = 1:4;
b = 1:3;
c = reshape( repmat(a, numel(b), 1), numel(a) * numel(b), 1 );
d = repmat(b(:), length(a), 1);
e = [c d]
e =
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
4 1
4 2
4 3
Конечно, вы можете избавиться от всех промежуточных переменных из приведенного выше примера.
Вы можете использовать простые старые матричные операции, например. в
x = [3,2,1];
y = [11,22,33,44,55];
v = [(ones(length(y),1) * x)(:), (ones(length(x), 1) * y)'(:)]
Изменить: это синтаксис Octave, MATLAB будет выглядеть следующим образом:
x = [3,2,1];
y = [11,22,33,44,55];
A = ones(length(y),1) * x;
B = (ones(length(x), 1) * y)';
v = [A(:) B(:)]
в обоих случаях результат будет
v =
3 11
3 22
3 33
3 44
3 55
2 11
2 22
2 33
2 44
2 55
1 11
1 22
1 33
1 44
1 55
Здесь больше MATLAB'esque способ найти комбинации. Это также можно легко расширить до более чем 2 векторов (а также не численных комбинаций):
v1 = 1: 1: 3;
v2 = 11: 11: 44;
v3 = 111:111:555;
dimensions = cellfun(@numel, {v1,v2,v3});
[i1,i2,i3] = ind2sub(dimensions, 1:prod(dimensions));
combinations = [v1(i1); v2(i2); v3(i3)]'
Что вы ищете, это декартовой продукт
cartprod - это функция, которая его реализует. Вы можете найти его в пакете линейной алгебры, поэтому вам нужно будет сделать:
>> pkg install -forge linear-algebra
>> pkg load linear-algebra
>> sortrows(cartprod(1:4,1:3))
ans =
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
4 1
4 2
4 3