【问题标题】:Indexing rows of a table by comparing the values between two cells通过比较两个单元格之间的值来索引表的行
【发布时间】:2025-12-20 02:30:07
【问题描述】:

我有一张类似上述附件的表格。 A 列和 B 列包含单元格数组方面的一些元素。我想创建第三列(级别)作为结果列;基于以下逻辑。

  1. 单元格 A 的值 = 单元格 B 的值的行将被标记为 1。 (在第 3 行,A 列的值 = B 列的值 = 3,因此标记为 1)。

  2. 接下来,前面的值将从所有 A列的单元格;并且将重复步骤 1,直到所有 行被标记。 (在第二步中,3将从所有 单元格,因此第 1 行和第 2 行都将标记为 2;在 最后一步,元素 {1,2} 将从最后一行中进一步删除 结果级别为 3 )

我正在使用 cell2matsetdiff 函数来比较单元格之间的值,但我无法构建上述 2 个逻辑步骤来成功运行我的代码。我刚刚开始学习 MATLAB,任何帮助将不胜感激。

【问题讨论】:

  • 如果 B 列的第 2 行是 3 而不是 2 会发生什么?这甚至可能吗?
  • @Leander,感谢您的评论。那是不可能的。假设一段时间,这是给定的数据。开发算法的逻辑是什么?有什么建议吗?

标签: matlab for-loop indexing comparison


【解决方案1】:

这是我能想到的最简单的答案,使用单个 while 循环并假设 AB 的单元格包含行向量:

Level = zeros(size(A));
index = cellfun(@isequal, A, B);
while any(index)
  Level(index) = max(Level)+1;      
  A = cellfun(@(c) {setdiff(c, unique([A{index}]))}, A);
  index = cellfun(@isequal, A, B);
end

上面的代码首先初始化了一个zeroesLevelA大小相同的矩阵来存储级别值。然后它使用cellfunisequal 找到AB 之间匹配单元格内容的logical index index。只要有index 指示的any 匹配,它将继续loopLevel 中的相应索引设置为Level 中的当前maximum value 加一。来自A 的所有匹配单元格内容都是concatenatedunique([A{index}]) 找到的unique 值。然后使用set difference 操作(与cellfun 一起)从A 中的每个单元格中删除匹配值,并用剩余值覆盖A。然后计算匹配的新index 并重新开始循环。

鉴于您的问题中的以下示例数据:

A = {[1 2 3]; [2 3]; 3; [1 2 3 4]};
B = {[1 2]; 2; 3; 4};

代码返回预期的层级向量:

Level =

     2
     2
     1
     3

【讨论】:

  • 老兄,非常感谢。你救了我。如果您能通过解释上述内容来帮我一个忙,我将不胜感激。我刚开始做MATLAB
  • @pradeepkumarTarei:我为所用函数添加了说明和一些文档链接。
  • 但是上面的代码不适用于大数据。请考虑以下事项。 A = {[1,5,6,9];[1,2,4,5,6,8,9,10];[1,2,3,4,5,6,8,9 ,10];[2,3,4,5,8,10];[1,2,3,4,5,6,8,10];[4,5,6,8,10];[4 ,5,7,10];[4,5,8,10];[2,3,4,5,6,8,9,10];[2,3,5,8,10]}; B = {[1,5];[2,4,5,9,10];[3,4,5,9,10];[2,3,4,5,8] ;[1,2,3,4,5,6,8,10];[5,6];[7];[4,5,8,10];[2,3,9];[2, 3,5,8,10]}; 正确答案为:[3,3,3,2,1,2,2,1,2,1]' by上述逻辑。但是,它产生 [0,0,0,0,1,0,2,1,0,1];这是错误的。任何建议/帮助将不胜感激。谢谢。
  • @pradeepkumarTarei:你的例子毫无意义。根据您在问题中的要求,在AB 之间匹配的任何行都应标记为1,然后将它们包含的值从A 的所有单元格中删除。这使得 A 有 5 个空单元格,1 个单元格有 7 个单元格,4 个单元格有 9 个。如果你想要不同的东西,你需要澄清你的问题。
  • 是的,你完全正确。请考虑以下作为附加限制。 1. A 和 B 之间匹配的任何行都应标记为 1,然后从 A 和 B 中删除相同的值。 A 和 B 之间匹配的任何空单元格将标记为相同(先前)级别。 (比如 2) 2. 任何不匹配的单元格值(或 A 列中的剩余值)将被标记为下一个。 (比如 3)上述 2 条件将产生所需的结果(如上例所示)。请建议/帮助我修改代码。
【解决方案2】:

不是我最好的工作,我认为可以摆脱内部循环。

% your testdata
A = {[1 2 3]
    [2 3]
    3
    [1,2,4]};
B = {[1 2]
    2
    3
    4};


Level = NaN(numel(B),1);
temp = A; % copy of A that we are going to remove elements from
k = 0; % loop couter
while any(isnan(Level)) % do until each element of Level is not NaN
    k = k+1; % increment counter by 1

    % step 1
    idx = find(cellfun(@isequal,temp,B)); % determine which cells are equal
    Level(idx) = k; % set level of equal cells

    % step 2
    for k = 1:numel(idx) % for each cell that is equal
        %remove values in B from A for each equal cell
        temp = cellfun(@setdiff,temp,repmat(B(idx(k)),numel(B),1),'UniformOutput',0);
    end   
end

【讨论】:

  • 但是上面的代码不适用于大数据。请考虑以下事项。 A = {[1,5,6,9];[1,2,4,5,6,8,9,10];[1,2,3,4,5,6,8,9,10] ;[2,3,4,5,‌​8,10];[1,2,3,4,5,6,8‌​,10];[4,5,6,8,10];[4‌ ​,5,7,10];[4,5,8,10];‌​[2,3,4,5,6,8,9,10];[​2,3,5,8, 10]}; B = {[1,5];[2,4,5,9,10];[3,4,5,9,10];[2,3,4,5,8];[1,2, 3,4,5,6,8,‌​10];[5,6];[7];[4,5,8‌​,10];[2,3,9];[2,3,5 ,‌​8,10]};正确答案应为:[3,3,3,2,1,2,2,1,2,1]' 按上述逻辑。但是,它产生 [0,0,0,0,1,0,2,1,0,1];这是错误的。任何建议/帮助将不胜感激。谢谢
最近更新 更多