【问题标题】:Shifting and adding more than two arrays with different lengths - MATLAB移动和添加两个以上不同长度的数组 - MATLAB
【发布时间】:2023-03-15 09:10:01
【问题描述】:

我有一个不同长度或大小的字符串或数组列表。我想使用最短的字符串,并通过将最短的字符串窗口一一移动来与其他字符串进行比较。

假设我想做加法,我有 [2 1 3] 作为我的最短列表并想在 [4 5 7 8 9] 上执行加法

1st addition: [2 1 3] + [4 5 7]
2nd addition: [2 1 3] + [5 7 8]
3rd addition: [2 1 3] + [7 8 9]

上面我发现的两个数组的例子可以用hankel函数解决。

a = [2 1 3];
b = [4 5 7 8 9];

idx = hankel(1:numel(a), numel(a):numel(b));
c = bsxfun(@plus, b(idx.'), a);

结果:

c =
     6     6    10   % [2 1 3] + [4 5 7]
     7     8    11   % [2 1 3] + [5 7 8]
     9     9    12   % [2 1 3] + [7 8 9]

但是现在,我想为他们所有人表演,并且有很多组合。假设数组ABCDE,所以可能的添加可以是A+BA+CA+DA+E、@987654 B+DB+EC+DC+ED+E

例如:

A=[2 1 3];B=[4 5 7 8 9];C=[6 9];D=[3 6 4 2 1 1];E=[4 6 9]

for A+B
 6  6  10  
 7  8  11  
 9  9  12

for A+C
 8 10
 7 12

for A+D
 5 7 7
 8 5 5
 6 3 4
 4 2 4

... and the rest

如何使用 MATLAB 做到这一点?非常感谢

【问题讨论】:

  • 如果a = [2 1 3]; b = [4 5 7 8 9];,什么是ABCDE
  • 到目前为止你尝试过什么?您现在只是在总结上一个问题的答案。
  • @Nick ,最后一个问题是只包含两个数组,现在我想将它扩展到两个以上的数组。谢谢

标签: arrays matlab combinatorics sliding-window


【解决方案1】:

使用适用于每一对的自定义函数,b 作为较大的(就元素数量而言)数组,核心功能是从您之前的案例中借用的 -

function out = testfunc1(a,b) %// Shift and add arrays with different lengths

if numel(a)>numel(b) %// swap a and b,as we want b to be the larger array
    tmp = a;
    a = b;
    b = tmp;
end
out = bsxfun(@plus, b(hankel(1:numel(a), numel(a):numel(b)).'), a);
return;

现在,在 arrayfun 中调用此函数,将所有这些汇总的数组作为单元格 -

%// Concatenate all variables into one cell array for processing with arrayfun
allvars = cat(1,{A},{B},{C},{D},{E}) 

%// Form all combinations between the variables
allcombs = allvars(nchoosek(1:numel(allvars),2));

%// Get summed results for each pair from all vars with one of the pairs always
%// being the first variable that represents A
out =arrayfun(@(n) testfunc1(allcombs{n,1},allcombs{n,2}), 1:size(allcombs,1),'un',0) 
celldisp(out)  %//display output

运行时输出 -

out{1} =
     6     6    10
     7     8    11
     9     9    12
out{2} =
     8    10
     7    12
out{3} =
     5     7     7
     8     5     5
     6     3     4
     4     2     4
out{4} =
     6     7    12
out{5} =
    10    14
    11    16
    13    17
    14    18
out{6} =
     7    11    11    10    10
    10     9     9     9    10
out{7} =
     8    11    16
     9    13    17
    11    14    18
out{8} =
     9    15
    12    13
    10    11
     8    10
     7    10
out{9} =
    10    15
    12    18
out{10} =
     7    12    13
    10    10    11
     8     8    10
     6     7    10

因此,out 的单元格分别代表您的A+BA+CA+DA+EB+CB+D 等输出。

【讨论】:

  • A+E 应该是6 7 12
  • @Cina 你能解释一下吗?也许用那个解释编辑你的问题?
  • @Divakar:hankel 解决方案中有一个小错误。您会看到hankel 返回列,并且由于我们正在使用行向量ab,因此我们必须在将索引用于b 之前转置索引并应用bsxfun 来广播添加。当ab 大小相同时,该错误尤其明显。无论如何,就像我说的那样,修复很容易,只需将转置移到括号内即可:)
  • @Amro 太棒了,是的,现在说得通了。谢谢!!
【解决方案2】:

这是我的版本:

% input arrays
A=[2 1 3]; B=[4 5 7 8 9]; C=[6 9]; D=[3 6 4 2 1 1]; E=[4 6 9];

% all possible pair combinations
pairs = nchoosek({A, B, C, D, E}, 2);

% make sure second one is the longest vector
ind = cellfun(@numel,pairs(:,1)) > cellfun(@numel,pairs(:,2));
pairs(ind,[1 2]) = pairs(ind,[2 1]);

c = cell(size(pairs,1),1);
for i=1:size(pairs,1)
    % the two vectors
    [a,b] = deal(pairs{i,:});

    % sliding window indices, and compute the sum
    idx = hankel(1:numel(a), numel(a):numel(b));
    c{i} = bsxfun(@plus, b(idx.'), a);
end

我正在重用solution from you previous question,并简单地将其应用于所有可能的配对,结果存储在一个单元格数组中:

>> celldisp(c)
c{1} =
     6     6    10
     7     8    11
     9     9    12
c{2} =
     8    10
     7    12
c{3} =
     5     7     7
     8     5     5
     6     3     4
     4     2     4
c{4} =
     6     7    12
c{5} =
    10    14
    11    16
    13    17
    14    18
c{6} =
     7    11    11    10    10
    10     9     9     9    10
c{7} =
     8    11    16
     9    13    17
    11    14    18
c{8} =
     9    15
    12    13
    10    11
     8    10
     7    10
c{9} =
    10    15
    12    18
c{10} =
     7    12    13
    10    10    11
     8     8    10
     6     7    10

每个单元格都匹配以下对(跨行读取):

>> nchoosek({'A', 'B', 'C', 'D', 'E'}, 2)
ans = 
    'A'    'B'
    'A'    'C'
    'A'    'D'
    'A'    'E'
    'B'    'C'
    'B'    'D'
    'B'    'E'
    'C'    'D'
    'C'    'E'
    'D'    'E'

【讨论】:

  • 出于某种原因,我认为 OP 只想要 A+B, A+C, A+D and A+E。我想我被帖子末尾显示的输出所吸引。你介意我在我的解决方案中使用nchoosek 吗? :)
  • @Amro 好的,所以编辑了我的解决方案,希望唯一借用的是 nchoosek
  • @Amro 有趣,这些 arrayfun 和 cellfun 无论如何都是循环代码,但 OP 可能更喜欢短/紧凑的代码 :) 你有我的 +1,主要是因为我不得不借用 nchoosek ;)
  • @Cina:啊,很好,我编辑了解决方案。修复非常简单,将bsxfun(@plus, b(idx).', a) 更改为bsxfun(@plus, b(idx.'), a)(在索引之前而不是之后转置索引)!
猜你喜欢
  • 2014-01-07
  • 2014-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-09
  • 2012-07-29
  • 2016-02-23
相关资源
最近更新 更多