【问题标题】:formatted print of structures contents and fieldnames in matlab/octavematlab/octave中结构内容和字段名的格式化打印
【发布时间】:2017-12-18 08:19:33
【问题描述】:

我需要将结构的内容与相应的字段名称和每个结构元素周围的一些文本打印到命令窗口。

This something [fieldname(i)] has the value of [struct.fieldname(i) value] something.

头疼了半天后,我得到了一个表达式(不起作用)和一个循环(起作用)。

问题 - 有没有办法在没有循环的情况下做到这一点?

代码:

box.apples = 25
box.cherries = 0.5
box.iron = 0.085

% Loop method (works)
for i = (1:length(struct2cell(box))) ;
    printf('There are %.3f kg of %s in the box \n', struct2cell(box){i}, fieldnames(box){i})
end
% Single expression method (doesn't work)
printf('There are %.3f kg of %s in the box \n', struct2cell(box){:}, fieldnames(box){:})

循环完全按照我的意愿返回合理的输出:

There are 25.000 kg of apples in the box 
There are 0.500 kg of cherries in the box
There are 0.085 kg of iron in the box

只是 printf 表达式返回这个奇怪的输出:

There are 25.000 kg of  in the box
There are 0.085 kg of apples in the box
There are 99.000 kg of herries in the box
There are 105.000 kg of ron in the box

建议

【问题讨论】:

  • 在开始之前,您是否确保您的箱子已清空?您发布的代码中没有任何地方可以输入 99 和 105。
  • 您提供的代码会出错,即使是循环版本?您使用的是哪个版本的 MATLAB?
  • @Flynn 我可以验证 105 神奇地出现了,我也得到了一些其他意想不到的值。我预计 105 来自 iron 中缺少的 i,如 char(105) = 'i',类似地,char(99) = 'c' 来自 'cherries'
  • @Wolfie 感谢关于字符转换的提示,我没有发现它!我在 Octave 4.2.1

标签: matlab struct printf octave cell-array


【解决方案1】:

在 GNU Octave 中(参见 Matlab 的 Wolfies anwer):

box.apples = 25
box.cherries = 0.5
box.iron = 0.085
printf('There are %.3f kg of %s in the box \n',
       horzcat(struct2cell(box),fieldnames(box))'{:});

并且出现“105.000”是因为您以 %f 的身份喂食“铁”。看看这个(这应该可以解释你奇怪的结果):

printf ('%f', 'iron')

【讨论】:

  • (struct2cell(box),fieldnames(box))'{:} 绝对不能在 matlab 中工作,但 OP 似乎无论如何都在使用 octave,这是一个很好的解决方案。
  • printf 在 MATLAB 中也不起作用,请参阅我的答案以获得摘要。
  • @Andy 非常感谢,我应该早点问的!我不确定为什么铁会被喂给 %f,尤其是为什么只有第一个字符。我需要仔细考虑你的答案。哦忘了提到我在 Octave 4.2.1
【解决方案2】:

此方法应适用于 MATLAB 和 Octave:

c = vertcat(struct2cell(box).',fieldnames(box).');
fprintf('There are %.3f kg of %s in the box \n', c{:});

在 MATLAB 中,您必须结束使用括号() 的语句。所以你不能这样做

c = struct2cell(box){:};

而且必须这样做

c = struct2cell(box);
c = c{:};

MATLAB 还要求您使用 fprintf,而不是 printf。你可以看到一些语言差异here


【讨论】:

    【解决方案3】:

    只需将我的 2 美分加到上述答案中即可。

    “无循环”不一定总是更快。尤其是现在使用 matlab 的 JIT 编译器 for 循环。所以不要仅仅为了有一个单线而避免循环并以丑陋的代码高尔夫结束。更不用说,单行不一定等于矢量化。如果对速度有疑问,请做一个简单的测试用例基准测试。

    此外,循环通常更具可读性,因此除非您通过避免它而获得巨大的加速,否则通常不一定值得为了微优化而牺牲可读性。

    话虽如此,下面是我编写该循环的方式:

      for CellStr = fieldnames(box).'
        Name = CellStr{1};
        fprintf('There are %.3f kg of %s in the box\n', box.(Name), Name)
      end
    

    或者,如果您使用八度,八度专门提供以下可爱的语法:

    for [Val, Field] = box
      fprintf('There are %.3f kg of %s in the box\n', Val, Field)
    end
    

    我机器上的一些基准测试(八度,无 JIT 编译,10000 次迭代后经过的时间):

    one-liner in answers above = 0.61343 seconds
    top loop shown above       = 0.92640 seconds
    bottom loop shown above    = 0.41643 seconds <-- wins
    loop shown in the question = 1.6744  seconds
    

    因此,请看,在这种特殊情况下,其中一种 for 循环方法实际上比单线方法更快


    还要注意box是matlab/octave中的函数名;使用隐藏内置函数的变量名通常是个坏主意。您通常可以通过对变量使用大写字母来解决这个问题,或者在调用您的变量之前简单地查找具有该名称的函数

    【讨论】:

    • 绝对正确,for [Val, Field] = box 语法真的很可爱 +1
    猜你喜欢
    • 1970-01-01
    • 2023-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-29
    相关资源
    最近更新 更多