从没有循环的两个数组元素成对创建数组
Create array from two arrays elements in pairs without loops
这里是一个简单的问题。我有数组:
a = [ 600 746 8556 90456 ]
b = [ 684 864 8600 90500 ]
我想得到:
output = [ a(1):b(1) a(2):b(2) a(3):b(3) a(4):b(4) ]
(或者 [ a(1):b(1); a(2):b(2); a(3):b(3); a(4):b(4) ]
,我不在乎)
如果不使用循环,我不知道如何做到这一点,但我知道这应该是一种方式。
有什么想法吗?
提前致谢
方法 #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).'
方法 #2
这里列出的是 cumsum
based approach that has to be more memory efficient and faster than both the earlier listed bsxfun
based approach and 。这是代码 -
%// 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
样本运行-
>> a
a =
6 12 43
>> b
b =
8 17 43
>> out
out =
6 7 8 12 13 14 15 16 17 43
单行使用 arrayfun, cell2mat and an anonymous function:
output = cell2mat(arrayfun(@(start, stop) start:stop, a, b, 'uni', 0))
解释:函数 arrayfun
并行迭代向量 a
和 b
,然后为它们的每一对元素调用匿名函数。匿名函数return是一个变长向量而不是标量,所以需要用'UniformOutput', false
(可以简写为'uni', 0
)使arrayfun
return 元胞数组。最后,您使用 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
这里是一个简单的问题。我有数组:
a = [ 600 746 8556 90456 ]
b = [ 684 864 8600 90500 ]
我想得到:
output = [ a(1):b(1) a(2):b(2) a(3):b(3) a(4):b(4) ]
(或者 [ a(1):b(1); a(2):b(2); a(3):b(3); a(4):b(4) ]
,我不在乎)
如果不使用循环,我不知道如何做到这一点,但我知道这应该是一种方式。
有什么想法吗?
提前致谢
方法 #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).'
方法 #2
这里列出的是 cumsum
based approach that has to be more memory efficient and faster than both the earlier listed bsxfun
based approach and
%// 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
样本运行-
>> a
a =
6 12 43
>> b
b =
8 17 43
>> out
out =
6 7 8 12 13 14 15 16 17 43
单行使用 arrayfun, cell2mat and an anonymous function:
output = cell2mat(arrayfun(@(start, stop) start:stop, a, b, 'uni', 0))
解释:函数 arrayfun
并行迭代向量 a
和 b
,然后为它们的每一对元素调用匿名函数。匿名函数return是一个变长向量而不是标量,所以需要用'UniformOutput', false
(可以简写为'uni', 0
)使arrayfun
return 元胞数组。最后,您使用 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