【问题标题】:How to query list of variables in Matlab struct matching a certain pattern?如何查询匹配某个模式的Matlab结构中的变量列表?
【发布时间】:2016-08-29 12:07:32
【问题描述】:

假设我在 Matlab 中有以下 struct(从 JSON 文件中读取):

>>fs.
fs.dichte              fs.hoehe               fs.ts2                 
fs.temperatur          fs.ts3                 fs.viskositaet
fs.ts1                 fs.ts4

每个fs.ts* 组件都包含另一个struct。在这种特殊情况下,ts 的索引从 1 变为 4,但在另一种情况下,它也可能是 2 或 7。你明白了吗?我希望程序足够灵活以处理任何可能的输入。 所以我的问题归结为:如何查询ts的最大索引? 在理想的世界中,这会起作用:

who fs.ts*

但不幸的是,它什么也没返回。有什么想法吗?

顺便说一句,我使用的是 Octave,没有可用于测试的 Matlab;但是,确实应该有一个适用于这两种环境的解决方案。

【问题讨论】:

  • 不是您确切问题的答案,但听起来您应该有一个带有列表的 ts 字段而不是 tsN 字段。提示:每次在变量或字段名称中看到数字时,请考虑是否不应该使用向量/数组/列表。
  • 好主意;我使用 JSON 的时间很短,所以我没有想到那个解决方案。所以我用一个名为ts 的对象数组替换了我的四个tsN。它被loadjson 正确解析。但是我怎样才能访问子结构呢? fs.ts(1) 工作并输出包含更多变量的结构,例如laengehoehe。但是fs.ts(1).laenge 给出:error: cell cannot be indexed with .
  • 从元胞数组中索引元素时需要使用大括号。如果你使用括号,那么你会得到一个单元数组切片。所以使用fs.ts{N},它返回元胞数组的元素N,而不是fs.ts(N),它返回一个元素为N的元胞数组。
  • 对,这样就可以了。为什么我自己没有想到呢? :-s 让我感到困惑的是,虽然fieldnames(fs.ts{1}) 呈现正确的结果,但自动完成在这里不起作用,所以如果我在交互式提示符下键入fs.ts{1}. 并按 TAB,变量不会列出(输出给出./ ../ .nargin.)。这还没有在 Octave GUI 中实现,还是普遍缺乏语言? Matlab 的行为方式是否相同?
  • Octave 依赖于 readline 来自动完成。您的建议是对 Octaves readline 配置的可能改进。请在Octave bug tracker建议。

标签: regex matlab struct octave matlab-struct


【解决方案1】:

您可以使用fieldnames 获取结构的所有字段名称,然后使用regexp 提取以ts 开头的那些并提取数字。然后您可以比较这些数字以找到最大的数字。

fields = fieldnames(fs);

number = str2double(regexp(fields, '(?<=^ts)\d+$', 'once', 'match'));
numbers = number(~isnan(number));

[~, ind] = max(number);
max_field = fields{ind};
max_value = fs.(max_field);

【讨论】:

  • 谢谢!这绝对帮助了我。我稍微修改了你的方法,因为在下一步中,我循环遍历tsNnumberOfParts = str2double(regexp(fields, '(?&lt;=^ts)\d+$', 'once', 'match'))';numberOfParts = numberOfParts(~isnan(numberOfParts(1, :)))(来自this answer 的cmets。然后我可以做for i = numberOfParts 等等......
  • @rotton 我将其合并到答案中。如果对您有用,请考虑将其标记为解决方案。
【解决方案2】:

不是您确切问题的答案,但听起来您应该有一个带有列表的 ts 字段,而不是 tsN 字段。

提示:每次在变量或字段名称中看到数字时,请考虑是否不应该使用向量/数组/列表。

这适用于所有语言,但对于 Octave 更是如此,因为一切都是数组。即使您拥有三个名为 ts1ts2ts3 且具有标量值的字段,您真正拥有的是三个字段,其值是大小为 1x1 的数组。

在 Octave 中,您可以拥有两件事。 ts 的值要么是一个元胞数组,元胞数组的每个元素都是一个标量结构;或者是一个结构数组。当每个结构都有不同的键时使用结构元胞数组,当所有结构都具有相同的键时使用结构数组。

结构体数组

octave> fs.ts = struct ("foo", {1, 2, 3, 4}, "bar", {"a", "b", "c", "d"});
octave> fs.ts # all keys/fields in the ts struct array
ans =

  1x4 struct array containing the fields:

    foo
    bar

octave> fs.ts.foo # all foo values in the ts struct array
ans =  1
ans =  2
ans =  3
ans =  4

octave> numel (fs.ts) # number of structs in the ts struct array
ans =  4

octave> fs.ts(1) # struct 1 in the ts struct array
ans =

  scalar structure containing the fields:

    foo =  1
    bar = a

octave> fs.ts(1).foo # foo value of the struct 1
ans =  1

标量结构元胞数组

但是,我不确定 JSON 是否支持结构数组之类的东西,您可能需要一个结构列表。在这种情况下,您将得到一个结构标量元胞数组。

octave> fs.ts = {struct("foo", 1, "bar", "a"), struct("foo", 2, "bar", "b"), struct("foo", 3, "bar", "c"), struct("foo", 4, "bar", "d"),};
octave> fs.ts # note, you actually have multiple structs
ans = 
{
  [1,1] =

    scalar structure containing the fields:

      foo =  1
      bar = a

  [1,2] =

    scalar structure containing the fields:

      foo =  2
      bar = b

  [1,3] =

    scalar structure containing the fields:

      foo =  3
      bar = c

  [1,4] =

    scalar structure containing the fields:

      foo =  4
      bar = d

}
octave-gui:28> fs.ts{1} # get struct 1
ans =

  scalar structure containing the fields:

    foo =  1
    bar = a

octave-gui:29> fs.ts{1}.foo # value foo from struct 1
ans =  1

【讨论】:

  • 好吧,虽然@Suever 的解决方案解决了我的具体问题,但您的回答/cmets 让我重新思考了我的数据结构。所以这让我想到了其他几个问题。那我应该开一个新的吗?我有一个可以公开分享的示例 JSON 文件。由于 SX 不允许我上传文件,我需要使用 pastebin 或类似的东西......
  • 您应该创建一个新问题,因为听起来您的新问题与此非常不同。您不需要上传文件或使用 pastebin。您应该创建一个minimal working example
猜你喜欢
  • 2014-12-29
  • 2021-12-30
  • 2021-04-13
  • 1970-01-01
  • 1970-01-01
  • 2019-09-05
  • 1970-01-01
  • 2018-10-25
  • 1970-01-01
相关资源
最近更新 更多