This is an archived low-energy page for bots and other anonmyous visitors.
Please sign up if you are a human and want to interact.
podian has asked for the wisdom of the Perl Monks concerning the following question:
Hello Monks,
when I want to split a string, I do this:
my ($x, $y, $z) = split(',', $_);
print "x = $x y= $y z =$z\n";
but if there are not enough tokens, then I get the following warning
Use of uninitialized value in concatenation (.) or string at ... (second line)
Is it possible to initialize the variables to nill - if they are not defined in the same line?
Thanks
Re: split and uninitialized variables
by amt (Monk) on Sep 03, 2004 at 11:05 UTC
|
You can silence your machines warnings by not using -w, or by "using" no warnings;. That's the quick fix, and probably appropriate for your solution.
The other option is to init those variables to "nill", but I don't know what this code does, so you need to weigh the two solutions.
| [reply] [d/l] |
Re: split and uninitialized variables
by Eimi Metamorphoumai (Deacon) on Sep 03, 2004 at 11:05 UTC
|
I'm sure there are a lot of ways to do that, but I'd probably go with
my ($x, $y, $z) = (split(',', $_), '' x 3);
which does the split, but also puts empty strings onto the end of the list. Then your variables grab the first three items from the list, running into the empty strings if they run out of data from the split.
Update: ambrus is right. That's what I get for testing code without warnings on. | [reply] [d/l] |
|
|
| [reply] |
|
|
I'm aware of the importance of clarity. If I were golfing I would have done something like
my ($x, $y, $z) = split(',', "$_,,");
but this was the most natural answer to me. The problem, as I saw it, was "sometimes the list returned by split is too short, and I want empty strings to fill missing places at the end," so the most natural answer I saw was to add items to fill it out. | [reply] [d/l] [select] |
|
|
my ($x, $y, $z) = (split(',', $_), ('') x 3);
will work.
| [reply] [d/l] [select] |
Re: split and uninitialized variables
by Arunbear (Prior) on Sep 03, 2004 at 11:08 UTC
|
You can do
my ($x, $y, $z) = ('', '', '');
($x, $y, $z) = split(',', $_);
OR
my ($x, $y, $z) = map { $_ || '' } split(',', $_);
to ensure the variables are initialised.
Update:
Oops! I really need a new brain.
use strict;
use warnings;
$_ = "a,0,b";
my ($x, $y, $z) = split(',', $_);
foreach ($x, $y, $z) { $_ = '' unless defined($_) }
print "x = $x\ny = $y\nz = $z\n";
__END__
x = a
y = 0
z = b
| [reply] [d/l] [select] |
|
|
$_ = 'a,b';
my ($x, $y, $z) = ('', '', '');
($x, $y, $z) = split(',', $_);
print(defined($z)?'defined':'undefined', "\n");
# prints undefined.
Your second solution
my ($x, $y, $z) = map { $_ || '' } split(',', $_);
erases any '0'. Try:
my ($x, $y, $z) = map { defined($_)?$_:'' } (split(',', $_))[0..2];
Personally, I'd go with the simple my ($x, $y, $z) = (split(',', $_), ('') x 3); solution mentioned elsewhere.
Update: Added missing [0..2] as pointed out by Roy Johnson. Thanks. | [reply] [d/l] [select] |
|
|
Actually, the map solution doesn't work, because split doesn't return three elements, so you'd need to make it
my ($x, $y, $z) = map { defined($_) ? $_ : '' } (split(/,/, $_))[0..2]
+;
Caution: Contents may have been coded under pressure.
| [reply] [d/l] |
|
|
main::(-e:1): 0
DB<1> $_ = "a,b"
DB<2> x ($x,$y,$z) = ('default') x 3
0 'default'
1 'default'
2 'default'
DB<3> x ($x,$y,$z) = split( ',', $_ )
0 'a'
1 'b'
2 undef
| [reply] [d/l] |
|
|
> perl -wl
my ($x,$y,$z) = ('','','');
($x,$y,$z) = split(',','a,b');
print "$x $y $z";
__END__
Use of uninitialized value in concatenation (.) or string at - line 3.
a b
> perl -wl
my ($x, $y, $z) = map { $_ || '' } split(',', 'a,0,b');
print "$x $y $z";
__END__
a b
The second one is easily fixed with:
perl -wl
my ($x, $y, $z) = map defined $_ ? $_ : '', (split(',', 'a,0,b'))[0..2
+];
print "$x $y $z";
__END__
a 0 b
Update: Doh! Thanks !1 (silly lurker).
antirice The first rule of Perl club is - use Perl The ith rule of Perl club is - follow rule i - 1 for i > 1
| [reply] [d/l] [select] |
Re: split and uninitialized variables
by jeffa (Bishop) on Sep 03, 2004 at 11:26 UTC
|
use strict;
use warnings;
use Data::Dumper;
my @key = qw(x y z);
my %hash;
while (<DATA>) {
chomp;
@hash{@key} = split ',';
print Dumper \%hash;
}
__DATA__
a,b,c
a,b
a,b,c,d
a,,,
[UPDATE] No. Scalars are not the better choice simply because you know what the data
that you are working on looks like. If you deal with multiple things, why not put them
in a container so you only have to move one thing around? :)
| [reply] [d/l] |
|
|
That is what I usually do. But if you know what the data you are working on, then scalars will be better.
One example could be "name, address-line1, address-line2"
and line 2 might be or might not be present.
So to summarise the replies, it would be better to initialize them in the next line.
All the other solutions seem to have some problems!
| [reply] |
|
|
my ( $foo, $bar, $baz );
$_ .= '' for ( $foo, $bar, $baz ) = split /,/;
Makeshifts last the longest.
| [reply] [d/l] |
Re: split and uninitialized variables
by ccn (Vicar) on Sep 03, 2004 at 12:00 UTC
|
my ($x, $y, $z) =
map { defined() ? $_ : '[undef]' }
split ',', $_, 3;
print "x = $x y= $y z =$z\n";
| [reply] [d/l] |
|
|