合并不同单元格的元素
Merging elements of different cells
假设,我们有一个由 id 和一个属性组成的元胞数组,例如
A{1,1}=[1 2;2 4]
A{1,2}=[2 3 5;8 5 6]
现在,我想要一个最终输出,其中包含两个单元格(第一行值)的唯一 ID,并且相应的列分别具有每个单元格的属性值。
即
C =
[1] [ 2]
[2] [1x2 double] % 4 in first cell and 8 in second cell
[3] [ 5]
[5] [ 6]
似乎无法使用 C=[unique(A{1,:}(1,:)')]
之类的东西。非常感谢任何帮助。
假设每个单元格都有两行和数量可变的列,其中第一行是 ID,第二行是一个属性,我会将所有单元格合并到一个二维矩阵中并使用 accumarray
。 accumarray
在这里非常合适,因为您想将属于同一 ID 的值分组在一起并对其应用函数。在我们的例子中,我们的函数将简单地将值放在元胞数组中,我们将确保对值进行排序,因为按每个 ID accumarray
分组的值以随机顺序进入函数。
使用 cell2mat
将单元格转换为二维矩阵,转置它以使其与 accumarray
兼容,然后使用它。我需要注意的一件事是,如果缺少任何 ID,accumarray
将使该插槽为空。我所说的缺失的意思是,在您的示例中,ID 4 缺失,因为 3 和 5 之间存在间隙,ID 6 也存在于 5 和 7 之间(我在您给我的评论中添加了示例)。因为数据中最大的 ID 是 7,所以 accumarray
通过以 1 为增量分配从 ID 1 到 ID 7 的输出。我们需要解决的最后一件事是从 accumarray
完成分组。
顺便说一句,我将假设您的单元格数组由 单行 单元格组成,就像您的示例一样……所以:
%// Setup
A{1,1}=[1 2;2 4];
A{1,2}=[2 3 5;8 5 6];
A{1,3}=[7;8];
%// Convert row of cell arrays to a single 2D matrix, then transpose for accumarray
B = cell2mat(A).';
%// Group IDs together and ensure they're sorted
out = accumarray(B(:,1), B(:,2), [], @(x) {sort(x)});
%// Add a column of IDs and concatenate with the previous output
IDs = num2cell((1:numel(out)).');
out = [IDs out];
%// Any cells from the grouping that are empty, eliminate
ind = cellfun(@isempty, out(:,2));
out(ind,:) = [];
我们得到:
out =
[1] [ 2]
[2] [2x1 double]
[3] [ 5]
[5] [ 6]
[7] [ 8]
>> celldisp(out(2,:))
ans{1} =
2
ans{2} =
4
8
如果您希望在二维元胞数组上完成此操作,其中此元胞数组的每一行代表同一问题的一个单独实例,我的一个建议是可能循环遍历每一行。像这样,在评论中给出你的例子:
%// Setup
A{1,1}=[1 2;2 4];
A{1,2}=[2 3 5;8 5 6];
A{1,3}=[7;8];
A{2,1}=[1 2;2 4];
A{2,2}=[1;7];
%// Make a cell array that will contain the output per row
out = cell(size(A,1),1);
for idx = 1 : size(A,1)
%// Convert row of cell arrays to a single 2D matrix, then transpose for accumarray
B = cell2mat(A(idx,:)).';
%// Group IDs together and ensure they're sorted
out{idx} = accumarray(B(:,1), B(:,2), [], @(x) {sort(x)});
%// Add a column of IDs and concatenate with the previous output
IDs = num2cell((1:numel(out{idx})).');
out{idx} = [IDs out{idx}];
%// Any cells from the grouping that are empty, eliminate
ind = cellfun(@isempty, out{idx}(:,2));
out{idx}(ind,:) = [];
end
我们得到:
>> out{1}
ans =
[1] [ 2]
[2] [2x1 double]
[3] [ 5]
[5] [ 6]
[7] [ 8]
>> out{2}
ans =
[1] [2x1 double]
[2] [ 4]
>> celldisp(out{1}(2,:))
ans{1} =
2
ans{2} =
4
8
>> celldisp(out{2}(1,:))
ans{1} =
1
ans{2} =
2
7
假设,我们有一个由 id 和一个属性组成的元胞数组,例如
A{1,1}=[1 2;2 4]
A{1,2}=[2 3 5;8 5 6]
现在,我想要一个最终输出,其中包含两个单元格(第一行值)的唯一 ID,并且相应的列分别具有每个单元格的属性值。 即
C =
[1] [ 2]
[2] [1x2 double] % 4 in first cell and 8 in second cell
[3] [ 5]
[5] [ 6]
似乎无法使用 C=[unique(A{1,:}(1,:)')]
之类的东西。非常感谢任何帮助。
假设每个单元格都有两行和数量可变的列,其中第一行是 ID,第二行是一个属性,我会将所有单元格合并到一个二维矩阵中并使用 accumarray
。 accumarray
在这里非常合适,因为您想将属于同一 ID 的值分组在一起并对其应用函数。在我们的例子中,我们的函数将简单地将值放在元胞数组中,我们将确保对值进行排序,因为按每个 ID accumarray
分组的值以随机顺序进入函数。
使用 cell2mat
将单元格转换为二维矩阵,转置它以使其与 accumarray
兼容,然后使用它。我需要注意的一件事是,如果缺少任何 ID,accumarray
将使该插槽为空。我所说的缺失的意思是,在您的示例中,ID 4 缺失,因为 3 和 5 之间存在间隙,ID 6 也存在于 5 和 7 之间(我在您给我的评论中添加了示例)。因为数据中最大的 ID 是 7,所以 accumarray
通过以 1 为增量分配从 ID 1 到 ID 7 的输出。我们需要解决的最后一件事是从 accumarray
完成分组。
顺便说一句,我将假设您的单元格数组由 单行 单元格组成,就像您的示例一样……所以:
%// Setup
A{1,1}=[1 2;2 4];
A{1,2}=[2 3 5;8 5 6];
A{1,3}=[7;8];
%// Convert row of cell arrays to a single 2D matrix, then transpose for accumarray
B = cell2mat(A).';
%// Group IDs together and ensure they're sorted
out = accumarray(B(:,1), B(:,2), [], @(x) {sort(x)});
%// Add a column of IDs and concatenate with the previous output
IDs = num2cell((1:numel(out)).');
out = [IDs out];
%// Any cells from the grouping that are empty, eliminate
ind = cellfun(@isempty, out(:,2));
out(ind,:) = [];
我们得到:
out =
[1] [ 2]
[2] [2x1 double]
[3] [ 5]
[5] [ 6]
[7] [ 8]
>> celldisp(out(2,:))
ans{1} =
2
ans{2} =
4
8
如果您希望在二维元胞数组上完成此操作,其中此元胞数组的每一行代表同一问题的一个单独实例,我的一个建议是可能循环遍历每一行。像这样,在评论中给出你的例子:
%// Setup
A{1,1}=[1 2;2 4];
A{1,2}=[2 3 5;8 5 6];
A{1,3}=[7;8];
A{2,1}=[1 2;2 4];
A{2,2}=[1;7];
%// Make a cell array that will contain the output per row
out = cell(size(A,1),1);
for idx = 1 : size(A,1)
%// Convert row of cell arrays to a single 2D matrix, then transpose for accumarray
B = cell2mat(A(idx,:)).';
%// Group IDs together and ensure they're sorted
out{idx} = accumarray(B(:,1), B(:,2), [], @(x) {sort(x)});
%// Add a column of IDs and concatenate with the previous output
IDs = num2cell((1:numel(out{idx})).');
out{idx} = [IDs out{idx}];
%// Any cells from the grouping that are empty, eliminate
ind = cellfun(@isempty, out{idx}(:,2));
out{idx}(ind,:) = [];
end
我们得到:
>> out{1}
ans =
[1] [ 2]
[2] [2x1 double]
[3] [ 5]
[5] [ 6]
[7] [ 8]
>> out{2}
ans =
[1] [2x1 double]
[2] [ 4]
>> celldisp(out{1}(2,:))
ans{1} =
2
ans{2} =
4
8
>> celldisp(out{2}(1,:))
ans{1} =
1
ans{2} =
2
7