您可以使用
diff
来找到不唯一的相邻位置,然后将其与
cumsum
结合使用,以生成应归属于彼此的不同组。在差异结果中查找任何非零值将找到连续的非唯一值。当您将
cumsum
应用于此结果时,将生成一个ID数组,该数组从1变化到许多组,其中属于同一ID的所有值都属于同一连续组。这应该作为输入到
accumarray
的理想输入,我们可以对属于每个组的所有值进行求和:
Aval = A(:);
ind = diff([Inf; Aval]) ~= 0;
IDs = cumsum(ind);
Aout = Aval(ind).';
Bout = accumarray(IDs(:), B(:)).';
我承认这不是几行代码就能概括的,大部分内容都是设置,但核心答案可以在第二、第三和最后一行代码中看到。请注意,在使用
accumarray
时需要输入
列向量,要强制将输入数据转换为列向量,我使用
(:)
将向量展开成列向量,无论它们的形状如何,特别是在第一行代码中。最后,我将结果进行转置,因为
accumarray
在这种情况下会输出一个列向量,而转置会创建一个行向量,而你想要的是行向量作为所需的结果。
对于您的测试输入:
A = [1 2 3 3 4 5 6 6 5 4 4 3 3 3 3];
B = [1 5 9 6 4 6 8 2 1 5 7 8 3 2 6];
diff
的输出结果如下所示:
>> ind.'
ind =
1 1 1 0 1 1 1 0 1 1 0 1 0 0 0
您可以准确地看到值为零的位置对应于非唯一连续位置。运行
cumsum
后,ID数组的输出如下:
>> IDs.'
IDs =
1 2 3 3 4 5 6 6 7 8 8 9 9 9 9
执行
cumsum
函数对 IDs 数组进行操作,可以将这个
diff
数组转换成每个连续组都给出一个唯一 ID 的形式。我们也可以使用
ind
索引到
A
中的每个唯一值所在的组,这是第三行代码。最后一行代码对每个组进行求和。请注意,第三行代码被转置为行向量,因为我展开了数据,使其成为一个列向量来处理。
我们得到了期望的输出结果:
>> Aout
Aout =
1 2 3 4 5 6 5 4 3
>> Bout
Bout =
1 5 15 4 6 10 1 12 19
cumsum
和accumarray
结合使用的技巧真是太棒了! - David Kaccumarray
和cumsum
是我最喜欢的两个函数之一。很高兴能与你分享这些! - rayryeng