从两个数组元素中成对创建数组,不带循环

myr*_*dio 4 arrays matlab vector vectorization

简单问题在这里.我有阵列:

a = [ 600 746 8556 90456 ]
b = [ 684 864 8600 90500 ]
Run Code Online (Sandbox Code Playgroud)

我想得到:

output = [ a(1):b(1) a(2):b(2) a(3):b(3) a(4):b(4) ]
Run Code Online (Sandbox Code Playgroud)

(或者[ a(1):b(1); a(2):b(2); a(3):b(3); a(4):b(4) ],我不在乎)

我不知道如何在不使用循环的情况下执行此操作,但我知道它应该是一种方式.

任何的想法?

提前致谢

Div*_*kar 8

方法#1

Vectorized具有bsxfun掩蔽能力的方法 -

%// Get "extents" formed with each pair of "a" and "b" and max extent
ext = b-a
max_ext = max(ext)

%// Extend all a's to max possible extent
allvals = bsxfun(@plus,a,[0:max_ext]')  %//'

%// Get mask of valid extensions and use it to have the final output
mask  = bsxfun(@le,[0:max_ext]',ext)  %//'
out  = allvals(mask).'
Run Code Online (Sandbox Code Playgroud)

方法#2

这里列出的是一种cumsum基于方法的方法,它必须比前面列出的bsxfun基于方法和arrayfun基于其他答案的方法更高效,更快.这是代码 -

%// Get "extents" formed with each pair of "a" and "b"
ext = b-a;

%// Ignore cases when "a" might be greater than "b"
a = a(ext>=0);
b = b(ext>=0);
ext = b-a;

if numel(ext)>1

    %// Strategically place "differentiated" values from array,a
    idx = ones(sum(ext+1),1);
    idx([1 cumsum(ext(1:end-1)+1)+1]) = [a(1) diff(a)-ext(1:end-1)];

    %// Perform cumulative summation to have the final output
    out = cumsum(idx)

else %// Leftover cases when there are one or no valid boundaries:(a->b)
    out = a:b
end
Run Code Online (Sandbox Code Playgroud)

样品运行 -

>> a
a =
     6    12    43
>> b
b =
     8    17    43
>> out
out =
     6     7     8    12    13    14    15    16    17    43
Run Code Online (Sandbox Code Playgroud)

  • 想要为第二种方法再给+1.如果a可能大于b`a = a(ext> = 0); b = b(ext> = 0);`应该作为第二行插入. (2认同)

Bas*_*els 7

单行使用arrayfun,cell2mat匿名函数:

output = cell2mat(arrayfun(@(start, stop) start:stop, a, b, 'uni', 0))
Run Code Online (Sandbox Code Playgroud)

说明:该函数arrayfun在向量并行迭代ab,然后调用每对它们的元素的匿名函数.匿名函数返回不同大小的向量而不是标量,因此您需要使用'UniformOutput', false(可以缩写为'uni', 0)来arrayfun返回单元格数组.最后,您使用cell2mat将单元阵列挤压到一个矢量中.

快速测试:

>> a = [10, 20, 40];
>> b = [13, 22, 45];
>> output = cell2mat(arrayfun(@(start, stop) start:stop, a, b, 'uni', 0))
output =
    10    11    12    13    20    21    22    40    41    42    43    44    45
Run Code Online (Sandbox Code Playgroud)