【问题标题】:Reading line by line does not work逐行阅读不起作用
【发布时间】:2014-04-19 21:54:44
【问题描述】:

我有一个这样的文件

key1 value1
key2 value2
key3 value3

等等

我想通过在空白处分割每一行来创建一个散列。我试过这样

while (<FILE>) {
  chomp;
  my ($key, $val) = split / /;
  $hash{$key} .= exists $hash{$key} ? ",$val" : $val;
} 

这给出了输出

key1 => value1, key2

其余行被忽略。

当我检查逐行阅读是否有效时,它没有。

它不会逐行读取,而是 while 循环只循环一次所有数据。

为什么要这样做?

【问题讨论】:

  • @user3353408:如果你想将$_拆分为任意空格组合,那么你需要split的默认行为,所以my ($key, $val) = split;可能更好

标签: perl hash while-loop split


【解决方案1】:

您将.= ",$val" 附加到每个哈希值,而不管它以前是否存在,因为$hash{$key} .= 隐式创建元素$hash{$key} 以便它可以接收分配。这意味着exists 将始终返回true,并且只会评估条件的第一个分支。任何数组或哈希元素都会发生这种情况

您的示例数据是错误的,因为它不包含等号=,但我认为您的意思是仅在哈希值已经包含数据时才将",$val"附加到哈希值。如果没有与$key对应的元素,则只需分配$val

也许是这样

use strict;
use warnings;

my %hash;

while (<DATA>) {
  chomp;
  my ($key, $val) = split /=/;
  if ( exists $hash{$key} ) {
    $hash{$key} .= ",$val";
  }
  else {
    $hash{$key} = $val;
  }
} 

use Data::Dump;
dd \%hash;

__DATA__
key1=value1
key2=value2
key3=value3
key1=value4
key2=value5

输出

{ key1 => "value1,value4", key2 => "value2,value5", key3 => "value3" }

更新

如果您真的想在一行中执行此操作(尽管我建议您不要这样做),您只需在代码中将 exists 替换为 defined,给出

  $hash{$key} .= defined $hash{$key} ? ",$val" : $val;

因为,虽然元素是自动激活的,所以存在它在接收到它的第一个值之前仍然没有任何价值,所以仍然没有定义

但是请使用简单的if 语句,这样自动激活的变幻莫测不会让必须维护您的代码的人复杂化


更新

这是另一种方式

$hash{$key} .= ',' if exists $hash{$key};
$hash{$key} .= $val;

这和标准if 都可以正常工作,因为条件是在评估.= 运算符之前测试的。只有当赋值使用条件表达式时,才会先执行.=

【讨论】:

  • 很好奇。 $hash{$key} .= exists $hash{$key} ? ... 的行为与 $hash{$key} = $hash{$key} . exists $hash{$key} ? ... 不同。
  • @mob:那么我们在perlbug 土地上,你应该报告它。你有演示问题的代码吗?如果您不愿意,我很乐意提出报告
  • perl -E 'say $x{y}.=exists $x{y}' 与 perl -E 'say $x{y}=$x{y}.exists $x{y}'
  • @mob:这很简洁,非常值得称赞。你会提出这个错误还是我应该提出?
猜你喜欢
  • 1970-01-01
  • 2016-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-17
相关资源
最近更新 更多