Struct 按字段名和一些非顺序索引选择结构元素

Struct 按字段名和一些非顺序索引选择结构元素,struct,octave,Struct,Octave,我的意思是使用结构来保存“表”: 第一行包含字段名。 假设我创建了一个结构 ds2 = struct( ... 'idx', { 1, 12 }, ... 'idxstr', { 'i01', 'i12' }, ... 'var1', { 3.5, 6.5 }, ... 'var2', { 21, 1 }, ... 'var3', { 5, 3 } ... ); 对于等于'i01'的idxstr对应的行,如何检索字段var2的值? 注: 我无法确保idx

我的意思是使用结构来保存“表”:

第一行包含字段名。 假设我创建了一个结构

ds2 = struct( ...
    'idx', { 1, 12 }, ...
    'idxstr', { 'i01', 'i12' }, ...
    'var1', { 3.5, 6.5 }, ...
    'var2', { 21, 1 }, ...
    'var3', { 5, 3 } ...
);
对于等于
'i01'
idxstr
对应的行,如何检索字段
var2
的值?

注:

  • 我无法确保
    idxstr
    元素的长度始终为3
  • 理想情况下,我会有一个方法也适用于包含字符串的列
    var2
    ,或任何其他类型的变量

  • PS:我想可以帮上忙。

    假设
    idxstr
    可以超过3个字符(有一个总是3个字符的较短版本),这就是我想到的(在MATLAB上测试):

    您可以通过以下方式访问变量:

    ds2(~cellfun(@isempty,strfind({ds2(:).idxstr},'i01'))).var2;
    % using above variable
    ds2(logical_index).var2;
    

    现在您可以理解为什么MATLAB引入了表hehe。

    假设
    idxstr
    可以超过3个字符(有一个总是3个字符的较短版本),这就是我想到的(在MATLAB上测试):

    您可以通过以下方式访问变量:

    ds2(~cellfun(@isempty,strfind({ds2(:).idxstr},'i01'))).var2;
    % using above variable
    ds2(logical_index).var2;
    

    现在您可以理解为什么MATLAB引入了表格呵呵。

    我把函数放在一起

    function el = struct_pick(s, cdata, cnames, rname)
        % Pick an element from a struct by column and row name
        coldata = vertcat(s.(cdata));
        colnames = mat2cell(vertcat(s.(cnames)), ones(1, length(s)));
        % This assumes rname is a string
        flt = strcmp(colnames, rname);
        el = coldata(logical(flt));
    endfunction
    
    这叫做

    % Pick an element by column and row name
    cdata = 'var3';
    cnames = 'idxstr';
    rname = 'i01';
    elem = struct_pick(ds2, cdata, cnames, rname);
    
    它似乎完成了任务。 我不知道这是否是一种不必要的做作方式

    仍然必须处理行名称不是字符串的可能性,如

    cnames = 'idx';
    rname = 1;
    
    编辑:如果
    idxstr
    中的字符串长度不同,则会引发
    错误:vertcat:cat:维度不匹配

    Ander Biguri的答案可以解决这个问题。

    我把函数放在一起

    function el = struct_pick(s, cdata, cnames, rname)
        % Pick an element from a struct by column and row name
        coldata = vertcat(s.(cdata));
        colnames = mat2cell(vertcat(s.(cnames)), ones(1, length(s)));
        % This assumes rname is a string
        flt = strcmp(colnames, rname);
        el = coldata(logical(flt));
    endfunction
    
    这叫做

    % Pick an element by column and row name
    cdata = 'var3';
    cnames = 'idxstr';
    rname = 'i01';
    elem = struct_pick(ds2, cdata, cnames, rname);
    
    它似乎完成了任务。 我不知道这是否是一种不必要的做作方式

    仍然必须处理行名称不是字符串的可能性,如

    cnames = 'idx';
    rname = 1;
    
    编辑:如果
    idxstr
    中的字符串长度不同,则会引发
    错误:vertcat:cat:维度不匹配

    Ander Biguri的答案可以解决这个问题。

    正如我在评论中提到的,我相信你的结构类型不适合这项工作。您不应该使用(实际上是单行)结构的数组,而应该使用带有“array”字段的单个结构。(数字或单元格,视情况而定)

    例如

    使用此结构,您的问题将变得非常容易处理:

    d.var2( strcmp( 'i01', d.idxstr ) )
    % ans = 21
    
    这也远比R/pandas数据帧功能更具可比性(也可以通过名称和大小相同的数组进行有效初始化)


    请仔细注意“idxstr”字段使用的语法:有一个带有单个元素的“outer”单元格数组,这意味着您只创建了一个结构,而不是一个结构数组。此单个元素恰好是字符串的单元格数组,其中此单元格数组与数字数组具有相同的大小(即具有相同的“行数”)

    更新

    作为对评论的回应,添加“行”应该相当简单。以下是一种方法:

    function S = addrow( S, R )
        FieldNames = fieldnames( S ).';   NumFields  = length( FieldNames );
        for i = 1 : NumFields,
            S.( FieldNames{i} ) = horzcat( S.( FieldNames{i} ), R{i} );
        end
    end
    
    然后你可以简单地做:

    d = addrow( d, {5, 'i011', 2.7, 10, 11} );
    

    正如我在评论中提到的那样,我相信你对这项工作的结构类型是错误的。您不应该使用(实际上是单行)结构的数组,而应该使用带有“array”字段的单个结构。(数字或单元格,视情况而定)

    例如

    使用此结构,您的问题将变得非常容易处理:

    d.var2( strcmp( 'i01', d.idxstr ) )
    % ans = 21
    
    这也远比R/pandas数据帧功能更具可比性(也可以通过名称和大小相同的数组进行有效初始化)


    请仔细注意“idxstr”字段使用的语法:有一个带有单个元素的“outer”单元格数组,这意味着您只创建了一个结构,而不是一个结构数组。此单个元素恰好是字符串的单元格数组,其中此单元格数组与数字数组具有相同的大小(即具有相同的“行数”)

    更新

    作为对评论的回应,添加“行”应该相当简单。以下是一种方法:

    function S = addrow( S, R )
        FieldNames = fieldnames( S ).';   NumFields  = length( FieldNames );
        for i = 1 : NumFields,
            S.( FieldNames{i} ) = horzcat( S.( FieldNames{i} ), R{i} );
        end
    end
    
    然后你可以简单地做:

    d = addrow( d, {5, 'i011', 2.7, 10, 11} );
    

    也许您可以使用
    strcmp

    >> [ds2.var2](strcmp('i01',{ds2.idxstr}))
    ans = 21
    

    也许您可以使用
    strcmp

    >> [ds2.var2](strcmp('i01',{ds2.idxstr}))
    ans = 21
    

    一点也不做作。这些事情不容易处理。我发现拥有一个数组结构要比拥有一个数组结构容易得多。i、 e.
    ds2.var1=[3.5,6.5]
    等使所有额外的事情变得更容易。一点也不做作。这些事情不容易处理。我发现拥有一个数组结构要比拥有一个数组结构容易得多。i、 e.
    ds2.var1=[3.5,6.5]
    等使所有额外的事情变得更容易。我确认这在Octave 5.1.0中对我有效。我确认这在Octave 5.1.0中对我有效。这篇文章强化了我的信念,即你真正想要的是数组结构,而不是数组结构。如果你有前者,这将是微不足道的;现在你有了后者,你需要经历各种各样的困难才能达到你的结果。这篇文章强化了我的信念,你真正想要的是数组结构,而不是数组结构。如果你有前者,这将是微不足道的;现在你有了后者,你需要经历各种困难才能达到你的结果。这在内存存储方面也更有效。我看到了两点优势。不利的一面是(这就是为什么我想用我的方式组织我的数据),在我的“表”中添加元素(相当于“行”)有点困难;我很少添加“columns”。@sancho.srestemonicacellio这也不会有太大问题。我用一个例子更新了答案。这在内存存储方面也更有效。我看到了两个优点。不利的一面是(这就是为什么我想用我的方式组织我的数据),这有点困难