【问题标题】:How can I return a list of hashrefs from a map in Perl?如何从 Perl 的映射中返回 hashref 列表?
【发布时间】:2009-09-10 06:07:16
【问题描述】:

我有以下大部分没问题的代码:

my $results = { data => [
   map {
      my $f = $_->TO_JSON;
      $f->{display_field} = $_->display_field($q);
      $f;
   } $rs->all
]};

只有我宁愿它更像以下:

my $results = { data => [
   map {
      %{$_->TO_JSON},
      display_field => $_->display_field($q),
   }, $rs->all
]};

但这会产生语法错误。我怎样才能做我想做的事,还是我当前的版本是最好的?

更新:对之前多出的分号感到抱歉。这里已经很晚了。不知道我是怎么错过的。谢谢大家!

【问题讨论】:

  • 其中任何一个都是丑陋的,但您的维护程序员有充分的理由追捕您并与您一起做可怕的事情。我猜对 $rs->all 的调用会返回一个数组?
  • @Manni 这难道不是 Perl 的重点吗? :->
  • 你很有趣,克里斯。我想知道我什么时候才能再次停止笑。哈。哈。哈。

标签: perl list map


【解决方案1】:

它只给出了一个语法错误,因为你 Perl 认为你需要在 map { ... } 之后省略逗号,因为它将映射解析为一个块,而不是一个表达式。将+ 放在前面会解决这个问题。此外,匿名哈希中不能有分号:

my $results = { data => [
   map +{
#      ^----------------- plus sign added
      %{$_->TO_JSON},
      display_field => $_->display_field($q);
#                                           ^---- should be comma or nothing
   }, $rs->all
]};

【讨论】:

  • 他不需要省略逗号。他需要它是一个匿名哈希引用,而不是一个代码块,在这种情况下,逗号是必要的。是 Perl 猜错了。
  • 啊,这似乎是一个很好的可能原因。我不知道我是如何在哈希引用中错过分号的。 +1
【解决方案2】:

问题在于 Perl 没有足够远地判断{ 是指“开始一个匿名哈希引用”还是“开始一个代码块”。它应该(理想情况下)查看相应的} 并查看是否有逗号,并采取相应的行动,但事实并非如此。它只向前看一点点,并试图猜测。而这一次是错误的,你会得到一个关于逗号的语法错误,它不应该存在,除了它应该不要移动它。

perldoc -f map 会告诉你这一切。基本上,它说如果你输入+{,Perl 会理解这意味着“不是代码块”并猜测它是一个哈希引用。这可能是您的语法错误的原因。作为另一个建议,map({ HASH STUFF }, $rs->all) 可能会起作用 - 我敢打赌 Perl 不会猜到它是这里的代码参考。

我无法让它工作,但没有$rs->TO_JSON 或名为$q 的变量我无论如何都无法让它工作。我希望这有帮助。如果没有,请发布更多代码。别担心,我们不咬人。

另外,既然我们在做,为什么不这样写呢:

my $results;
$results->{data} = [ map MAGIC MAP STUFF, $rs->all ];

可以说更具可读性,尤其是当您一次向$results 添加大量内容时。

【讨论】:

  • +{ 在这种情况下由于某些奇怪的原因根本不起作用。试图找出原因。
  • 我也是。您可以尝试使用括号:map({ HASH STUFF }, $rs->all)
  • 找出原因;看我的回答。奇怪的是,$hashref = { foo => 1, bar => 2 ; } 是一个错误。
  • 我刚看到。我不知道我是怎么错过它的,而且我几乎认为 Perl 不应该抱怨它接受的其他一些东西,但这很可能是这里的罪魁祸首。
【解决方案3】:

我不完全确定您要寻找什么样的结构。第一个示例中的 map 已经返回了一个 hashref 列表($f 的每个版本)。

如果您只是想要类似于第二个示例的语法,那么您几乎是对的;您需要去掉 map 块中多余的分号,并使用一对花括号来创建匿名哈希引用。

类似:

my $results = { data => [
    map { { %{$_->TO_JSON},
            display_field => $_->display_field($q)
          }
    } $rs->all
]};

【讨论】:

  • 你是对的,也可以通过一元+编译器提示来完成。我更喜欢这种方式,因为它更清晰(恕我直言)。
  • 这是有争议的。我更喜欢在 map() 的参数周围加上括号,因为这里“更具可读性”,但我绝对同意双括号比 +{ 更明显,无论双括号看起来多么丑陋。
【解决方案4】:

我总是以块的形式使用 map,并构造代码以便于区分。虽然你可以在开头的花括号前面加上一个 + 来使用表达形式,但这对你来说真的那么重要吗?

除此之外,您的第一个示例看起来还不错。继续前进并解决实际问题。 :)

【讨论】:

    猜你喜欢
    • 2015-01-19
    • 2011-09-29
    • 1970-01-01
    • 1970-01-01
    • 2010-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多