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
元素的长度始终为3var2
,或任何其他类型的变量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这也不会有太大问题。我用一个例子更新了答案。这在内存存储方面也更有效。我看到了两个优点。不利的一面是(这就是为什么我想用我的方式组织我的数据),这有点困难