convert integer to string

  • Follow


This is embarrassing!

I read an input file, split each row on the separators, pick out the
unique key (which consists of seven digits), create a hash element on
the key, and read the other values into an anonymous hash. This has
worked for years without a hitch.

Yesterday, my user requested the app to print a calculated field,
which is a list of names contained in a secondary file. I thought, "No
problem, I'll just create a new element in my anonymous hash,
concatenate each name unless the name already matched the string, and
print it out." Didn't work, but the errors seemed to be random and
arbitrary.

After a couple of hours, I used bdf's trick to print out the hash, and
discovered much to my embarrassment that the keys weren't the same. In
the main loop where I created the hash, the keys were as expected and
consisted of seven characters which are all digits. HOWEVER, in the
loop where I created the additional hash element, the keys with
leading zeros did not match. Here is an example of the hash:

0123456 => HASH(deadbeed)
  id => 0123456
  name => joe
  gender => male
  new_field =>
123456 =>  HASH(deadbeef)
  new_field => list of concatenated strings

I read the main file and create the main hash on the unique key, one
element of which is 'new_field' with an initial value of ' '. Then, I
read a secondary file which contains the key and ATTEMPT to
concatenate an element to the main hash element new_field. Instead, it
creates a new hash element with the numeric value of the unique key
instead of the string value.

So, I guess my question is how I convert an integer to a string to
preserve the leading zeros.

According to MJD on his infrequently asked questions page, the answer
is, "Try using a whip." But that doesn't tell me what kind of whip.
http://perl.plover.com/IAQ/IAQlist.html#how_can_i_force_perl_to_treat_a_number_as_a_string

CC.
0
Reply cartercc (420) 6/8/2010 6:10:00 PM

> So, I guess my question is how I convert an integer to a string to
> preserve the leading zeros.
>
> According to MJD on his infrequently asked questions page, the answer
> is, "Try using a whip." But that doesn't tell me what kind of whip.
> http://perl.plover.com/IAQ/IAQlist.html#how_can_i_force_perl_to_treat_a_number_as_a_string
The whip I usually use is string concatenation or variable interpolation 
within double quotes.
Something like

my $number=5;
my $string="000".$number;

Surely there are several ways to do this.
This always works for me! :)

0
Reply Ralph 6/8/2010 6:19:10 PM


>>>>> "c" == ccc31807  <cartercc@gmail.com> writes:

  c> After a couple of hours, I used bdf's trick to print out the hash, and
  c> discovered much to my embarrassment that the keys weren't the same. In
  c> the main loop where I created the hash, the keys were as expected and
  c> consisted of seven characters which are all digits. HOWEVER, in the
  c> loop where I created the additional hash element, the keys with
  c> leading zeros did not match. Here is an example of the hash:

what trick? use Data::Dumper and no trick is needed.

  c> 0123456 => HASH(deadbeed)
  c>   id => 0123456

that is an OCTAL literal. when parsed into perl it will be converted to
an integer and later printed in decimal. if those are always keys which
means strings, never print or use them without quotes. don't think of
them as numbers but strings with all digits.

  c> So, I guess my question is how I convert an integer to a string to
  c> preserve the leading zeros.

if you already have corrupted numbers, use sprintf to pad them with
zeros. but i suspect you will still have nasty errors as you will have
converted from the literal octal value now to a decimal. you can sprintf
the number back in octal to compensate. the proper solution is to never
let perl see those as literal octal numbers but always as strings. i
dunno what your code is doing (as you didn't post any) to make this
happen. are you doing an eval on some incoming data? that is a no-no! do
a proper parse and you can keep those keys as strings.

uri

-- 
Uri Guttman  ------  uri@stemsystems.com  --------  http://www.sysarch.com --
-----  Perl Code Review , Architecture, Development, Training, Support ------
---------  Gourmet Hot Cocoa Mix  ----  http://bestfriendscocoa.com ---------
0
Reply Uri 6/8/2010 6:26:10 PM

On Jun 8, 2:26=A0pm, "Uri Guttman" <u...@StemSystems.com> wrote:
> dunno what your code is doing (as you didn't post any) to make this
> happen. are you doing an eval on some incoming data? that is a no-no! do
> a proper parse and you can keep those keys as strings.

This is what I'm doing.

The main file looks like this:
0123456|joe|male|etc ...

which I manipulate as follows:
my ($id, $name, $gender, @rest) =3D split /\|/;
$main_hash{$id} =3D {
  id =3D> $id,
  name =3D> $name.
  gender =3D> $gender,
  rest =3D> @rest,
  new_value =3D> ' ',
 };

The secondary file looks like this:
0123456|this|etc ...
0123456|is|etc ...
0123456|a|etc ...
0123456|list|etc ...
0123456|of|etc ...
0123456|strings|etc ...

which I manipulate as follows:
my ($id, $string, @rest) =3D split /\|/;
$main_hash{$id}{new_value} .=3D $string unless $main_hash{$id}
{new_value} =3D~ /$string/; #the strings can be duplicated but I only
want one of each

So, should I double quote the $id when I use it as a hash key? That
strikes me as idiosyncratic even for Perl.

CC.
0
Reply ccc31807 6/8/2010 6:45:01 PM

Quoth ccc31807 <cartercc@gmail.com>:
> On Jun 8, 2:26�pm, "Uri Guttman" <u...@StemSystems.com> wrote:
> > dunno what your code is doing (as you didn't post any) to make this
> > happen. are you doing an eval on some incoming data? that is a no-no! do
> > a proper parse and you can keep those keys as strings.
> 
> This is what I'm doing.
> 
> The main file looks like this:
> 0123456|joe|male|etc ...
> 
> which I manipulate as follows:
> my ($id, $name, $gender, @rest) = split /\|/;
> $main_hash{$id} = {

'%main_hash' is an appallingly bad name for a variable. Why is it there?
What's it got in it? (In this case, probably, something like '%people'
might be better.)

>   id => $id,
>   name => $name.
>   gender => $gender,
>   rest => @rest,

This line does not do what you think it does.

>   new_value => ' ',
>  };
> 
> The secondary file looks like this:
> 0123456|this|etc ...
> 0123456|is|etc ...
> 0123456|a|etc ...
> 0123456|list|etc ...
> 0123456|of|etc ...
> 0123456|strings|etc ...
> 
> which I manipulate as follows:
> my ($id, $string, @rest) = split /\|/;
> $main_hash{$id}{new_value} .= $string unless $main_hash{$id}
> {new_value} =~ /$string/; #the strings can be duplicated but I only

You want \Q\E here.

> want one of each
> 
> So, should I double quote the $id when I use it as a hash key? That
> strikes me as idiosyncratic even for Perl.

Works for me:

    ~% perl -E'
        my %main_hash;
        {
            my $line = "0123456|joe|male|etc";
            my ($id, $name, $gender) = split /\|/, $line;
            $main_hash{$id} = {
                id => $id,
                name => $name,
                gender => $gender,
                new_value => " ",
            };
        }
        for my $line ("0123456|this|etc", "0123456|is|etc") {
            my ($id, $string) = split /\|/, $line;
            $main_hash{$id}{new_value} .= $string
                unless $main_hash{$id}{new_value} =~ /\Q$string/;
        }
        for (keys %main_hash) {
            say "$_: $main_hash{$_}{new_value}";
        }
    '
    0123456: this

(There's only one entry because "this" =~ /is/.)

So you must be doing something else.

Ben

0
Reply Ben 6/8/2010 7:06:46 PM

ccc31807 wrote:
> On Jun 8, 2:26 pm, "Uri Guttman" <u...@StemSystems.com> wrote:
>> dunno what your code is doing (as you didn't post any) to make this
>> happen. are you doing an eval on some incoming data? that is a no-no! do
>> a proper parse and you can keep those keys as strings.
> 
> This is what I'm doing.
> 
> The main file looks like this:
> 0123456|joe|male|etc ...
> 
> which I manipulate as follows:
> my ($id, $name, $gender, @rest) = split /\|/;
> $main_hash{$id} = {
>   id => $id,
>   name => $name.
>   gender => $gender,
>   rest => @rest,
>   new_value => ' ',
>  };
> 
> The secondary file looks like this:
> 0123456|this|etc ...
> 0123456|is|etc ...
> 0123456|a|etc ...
> 0123456|list|etc ...
> 0123456|of|etc ...
> 0123456|strings|etc ...
> 
> which I manipulate as follows:
> my ($id, $string, @rest) = split /\|/;
> $main_hash{$id}{new_value} .= $string unless $main_hash{$id}
> {new_value} =~ /$string/; #the strings can be duplicated but I only
> want one of each
> 
> So, should I double quote the $id when I use it as a hash key? That
> strikes me as idiosyncratic even for Perl.
> 
> CC.

Provide actual code that we can run that shows your issue and so we can
see what's happening.
0
Reply J 6/8/2010 7:18:58 PM

ccc31807 wrote:
> This is embarrassing!
> 
> I read an input file, split each row on the separators, pick out the
> unique key (which consists of seven digits), create a hash element on
> the key, and read the other values into an anonymous hash. This has
> worked for years without a hitch.
> 
> Yesterday, my user requested the app to print a calculated field,
> which is a list of names contained in a secondary file. I thought, "No
> problem, I'll just create a new element in my anonymous hash,
> concatenate each name unless the name already matched the string, and
> print it out." Didn't work, but the errors seemed to be random and
> arbitrary.
> 
> After a couple of hours, I used bdf's trick to print out the hash, and
> discovered much to my embarrassment that the keys weren't the same. In
> the main loop where I created the hash, the keys were as expected and
> consisted of seven characters which are all digits. HOWEVER, in the
> loop where I created the additional hash element, the keys with
> leading zeros did not match. Here is an example of the hash:

Most folks really don't need to know the backstory. Post your code,
your results, your expectations, and your questions.
0
Reply J 6/8/2010 7:22:18 PM

On Jun 8, 3:18=A0pm, "J. Gleixner" <glex_no-s...@qwest-spam-no.invalid>
wrote:
> Provide actual code that we can run that shows your issue and so we can
> see what's happening.

Here is the working code in my test script. Unfortunately, I can't
post the data files. Note that this code does some other things and
contains debugging statements.

open FAC, '<', "FAC_${term}.csv", or die "Cannot open FAC, $!";
chomp ($header =3D <FAC>);
while (<FAC>)
{
	next unless /\w/;
	chomp;
	my ($changed, $last, $first, $middle, $id2, $region, $contract,
$addy1, $addy2, $csz, $mail, $trs, @courses) =3D  parse_line(',', $bool,
$_);
	print "id2 is [$id2] and facid is [$facid]\n";
	if ($facid !~ /\?/) { next unless $id2 eq $facid; }
	$fac{$id2} =3D {
	id2 =3D> $id2,
	contract =3D> $contract,
	first =3D> $first,
	middle =3D> $middle,
	last =3D> $last,
	addy1 =3D> $addy1,
	addy2 =3D> $addy2,
	csz =3D> $csz,
	mail =3D> $mail,
	trs =3D> $trs,
	courses =3D> @courses,
	xlist =3D> '',
	}
}
close FAC;

open SEC, '<', "$sections_file", or die "Cannot open SEC, $!";
chomp ($header =3D <SEC>);
while (<SEC>)
{
	next unless /\w/;
	chomp;
	s/'/\\'/g;
   my ($last, $first, $middle, $id1, $filename, $crs_id, $site, $loc,
$glcode, $level, $count, $status, $section, $title, $hours, $xlist,
$total, $travel, $contract) =3D parse_line(',', 0, $_);
	next if $contract =3D~ /N/;
	$sec{$crs_id} =3D {
	crs_id =3D> $crs_id,
	filename =3D> $filename,
	id1 =3D> $id1,
	site =3D> $site,
	loc =3D> $loc,
	glcode =3D> $glcode,
	level =3D> $level,
	count =3D> $count,
	status =3D> $status,
	section =3D> $section,
	title =3D> $title,
	hours =3D> $hours,
	xlist =3D> $xlist,
	total =3D> $total,
	travel =3D> $travel,
	contract =3D> $contract,
	};
	$xlist{$id1} .=3D "$section " if $xlist =3D~ /\d/ and $xlist !~ /
$section/;
	$fac{$id1}{xlist} .=3D "$section " if $xlist =3D~ /\d/;
}
close SEC;



0
Reply ccc31807 6/8/2010 7:27:48 PM

>>>>> "c" == ccc31807  <cartercc@gmail.com> writes:

  c> On Jun 8, 2:26�pm, "Uri Guttman" <u...@StemSystems.com> wrote:
  >> dunno what your code is doing (as you didn't post any) to make this
  >> happen. are you doing an eval on some incoming data? that is a no-no! do
  >> a proper parse and you can keep those keys as strings.

  c> This is what I'm doing.

  c> The main file looks like this:
  c> 0123456|joe|male|etc ...

  c> which I manipulate as follows:
  c> my ($id, $name, $gender, @rest) = split /\|/;
  c> $main_hash{$id} = {
  c>   id => $id,
  c>   name => $name.
  c>   gender => $gender,
  c>   rest => @rest,

that is wrong as it will put the whole array there. you need a ref to
that array or an anon ref.

  c>   new_value => ' ',
  c>  };

  c> The secondary file looks like this:
  c> 0123456|this|etc ...
  c> 0123456|is|etc ...
  c> 0123456|a|etc ...
  c> 0123456|list|etc ...
  c> 0123456|of|etc ...
  c> 0123456|strings|etc ...

  c> which I manipulate as follows:
  c> my ($id, $string, @rest) = split /\|/;
  c> $main_hash{$id}{new_value} .= $string unless $main_hash{$id}
  c> {new_value} =~ /$string/; #the strings can be duplicated but I only
  c> want one of each

  c> So, should I double quote the $id when I use it as a hash key? That
  c> strikes me as idiosyncratic even for Perl.

in that limited code i don't see where the keys would be interpreted as
literal numbers. there must be something else going on which is doing
that. perl won't lose leading zeroes in strings without doing some
number conversions. are you sure you never look at those kays as
numbers? like use == to check them or similar? since they seem to be
fixed size you can always use the string comparison ops safely.

uri

-- 
Uri Guttman  ------  uri@stemsystems.com  --------  http://www.sysarch.com --
-----  Perl Code Review , Architecture, Development, Training, Support ------
---------  Gourmet Hot Cocoa Mix  ----  http://bestfriendscocoa.com ---------
0
Reply Uri 6/8/2010 7:28:18 PM

>>>>> "c" == ccc31807  <cartercc@gmail.com> writes:

  c> On Jun 8, 3:18�pm, "J. Gleixner" <glex_no-s...@qwest-spam-no.invalid>
  c> wrote:
  >> Provide actual code that we can run that shows your issue and so we can
  >> see what's happening.

  c> Here is the working code in my test script. Unfortunately, I can't
  c> post the data files. Note that this code does some other things and
  c> contains debugging statements.

  c> open FAC, '<', "FAC_${term}.csv", or die "Cannot open FAC, $!";
  c> chomp ($header = <FAC>);
  c> while (<FAC>)
  c> {
  c> 	next unless /\w/;
  c> 	chomp;
  c> 	my ($changed, $last, $first, $middle, $id2, $region, $contract,
  c> $addy1, $addy2, $csz, $mail, $trs, @courses) =  parse_line(',', $bool,
  c> $_);
  c> 	print "id2 is [$id2] and facid is [$facid]\n";
  c> 	if ($facid !~ /\?/) { next unless $id2 eq $facid; }
  c> 	$fac{$id2} = {
  c> 	id2 => $id2,
  c> 	contract => $contract,
  c> 	first => $first,
  c> 	middle => $middle,
  c> 	last => $last,
  c> 	addy1 => $addy1,
  c> 	addy2 => $addy2,
  c> 	csz => $csz,
  c> 	mail => $mail,
  c> 	trs => $trs,
  c> 	courses => @courses,

same bug as i pointed out in another post. you need a ref or anon array
there. that is very wrong. who knows what it is doing to your app?

  c> 	xlist => '',
  c> 	}

uri

-- 
Uri Guttman  ------  uri@stemsystems.com  --------  http://www.sysarch.com --
-----  Perl Code Review , Architecture, Development, Training, Support ------
---------  Gourmet Hot Cocoa Mix  ----  http://bestfriendscocoa.com ---------
0
Reply Uri 6/8/2010 7:31:28 PM

On Jun 8, 3:06=A0pm, Ben Morrow <b...@morrow.me.uk> wrote:
> '%main_hash' is an appallingly bad name for a variable. Why is it there?
> What's it got in it? (In this case, probably, something like '%people'
> might be better.)


Sorry. I posted the code where I populated the two hashes, named %fac
and %sec.

> You want \Q\E here.

Trying that now.

> So you must be doing something else.

Not intentionally.

CC.
0
Reply ccc31807 6/8/2010 7:34:09 PM

On Jun 8, 3:31=A0pm, "Uri Guttman" <u...@StemSystems.com> wrote:
> =A0 c> =A0 =A0 =A0 =A0 courses =3D> @courses,
>
> same bug as i pointed out in another post. you need a ref or anon array
> there. that is very wrong. who knows what it is doing to your app?

@courses contains a list of numeric keys. If I:
print "Courses: [@courses]\n";
it will output something like this:
Courses: [23456 34567 45678]

This is NOT the problem here. What this does is make the hash element
$fac{$id}{courses} contain a scalar value like this:
'23456 34567 45678' This works perfectly and does exactly what I want
it to.

But thanks for pointing this out, CC.
0
Reply ccc31807 6/8/2010 7:40:35 PM

ccc31807 wrote:
) On Jun 8, 3:31?pm, "Uri Guttman" <u...@StemSystems.com> wrote:
)> ? c> ? ? ? ? courses => @courses,
)>
)> same bug as i pointed out in another post. you need a ref or anon array
)> there. that is very wrong. who knows what it is doing to your app?
)
) @courses contains a list of numeric keys. If I:
) print "Courses: [@courses]\n";
) it will output something like this:
) Courses: [23456 34567 45678]
)
) This is NOT the problem here. What this does is make the hash element
) $fac{$id}{courses} contain a scalar value like this:
) '23456 34567 45678' This works perfectly and does exactly what I want
) it to.

No, it doesn't.

It would if you spelled it like this:

   courses => "@courses",

But now, it would make:

  $fac{$id}{courses} contain '23456', and
  $fac{$id}{34567} contain '45678'.

And count yourself lucky that there are an odd number of elements,
otherwise the following keys and values would be swapped around.


SaSW, Willem
-- 
Disclaimer: I am in no way responsible for any of the statements
            made in the above text. For all I know I might be
            drugged or something..
            No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
0
Reply Willem 6/8/2010 8:05:00 PM

ccc31807 wrote:
> On Jun 8, 3:18 pm, "J. Gleixner" <glex_no-s...@qwest-spam-no.invalid>
> wrote:
>> Provide actual code that we can run that shows your issue and so we can
>> see what's happening.
> 
> Here is the working code in my test script. Unfortunately, I can't
> post the data files. Note that this code does some other things and
> contains debugging statements.

How can we run this?

Create a short example we can run that shows the issue. Just
populate an array or two with example data and use that
in place of your files.

Narrow your example code down to the issue, get rid of all the other
stuff and you might find the problem on your own.
0
Reply J 6/8/2010 8:06:15 PM

On Jun 8, 4:05=A0pm, Willem <wil...@turtle.stack.nl> wrote:
> ) This is NOT the problem here. What this does is make the hash element
> ) $fac{$id}{courses} contain a scalar value like this:
> ) '23456 34567 45678' This works perfectly and does exactly what I want
> ) it to.
>
> No, it doesn't.

I beg to differ, but it does. I've been running this particular piece
of code for about three years, and it has exactly the behavior I
described. This is a line from my debugging file with only the
personal information replaced with XXXXX.

1073251 =3D> HASH(0x1e4ea6c)
     xlist =3D>
     middle =3D> A
     first =3D> XXXXX
     contract =3D> XXXXX
     csz =3D> XXXXX
     addy2 =3D>
     courses =3D> 235519 235524 237125
     last =3D> XXXXX
     id2 =3D> 1073251
     addy1 =3D> XXXXX Drive
     mail =3D> XXXXX@XXXXX
     trs =3D> Current Member
0
Reply ccc31807 6/8/2010 8:16:20 PM

On Jun 8, 2:10=A0pm, ccc31807 <carte...@gmail.com> wrote:
> This is embarrassing!

Okay, now I really am embarrassed. It's not a Perl problem at all --
it's a Microsoft problem.

The script that I reference is the third one out of four, the whole
process takes about six input files and outputs several thousand PDF
files. I get the data from various people and a couple of databases.

I get some of the data in CSV format. One of my sources switched from
an Access database to an Excel file. Turns out that Excel strips out
the leading zeros if it thinks that the datum is an integer.

I really, really should have learned this lesson by now -- check the
code, check the data. Yes, I mostly validate the data as it comes in,
checking the format and so on, and the particular numeric datum I used
as a key validated as numeric. It never occurred to me to look at the
data file until after I spent several hours checking and rechecking my
code and posting on c.l.p.m.

'Garbage in, garbage out' isn't always the result of bad code, it can
be the result of bad data. Thanks to all, and please accept my apology
for the excitement.

CC.
0
Reply ccc31807 6/8/2010 8:27:36 PM

>>>>> "c" == ccc31807  <cartercc@gmail.com> writes:

  c> On Jun 8, 4:05�pm, Willem <wil...@turtle.stack.nl> wrote:
  >> ) This is NOT the problem here. What this does is make the hash element
  >> ) $fac{$id}{courses} contain a scalar value like this:
  >> ) '23456 34567 45678' This works perfectly and does exactly what I want
  >> ) it to.
  >> 
  >> No, it doesn't.

  c> I beg to differ, but it does. I've been running this particular piece
  c> of code for about three years, and it has exactly the behavior I
  c> described. This is a line from my debugging file with only the
  c> personal information replaced with XXXXX.

then that is not the code that you are using. it will put the list of
courses into the hash as key/value pairs. the only way you get what you
claim is with "@courses". did you lose the quotes in pasting? if you
claim that, show exact runnable code that does this. you can whip up an
dummy example in 2 minutes. here is one:

perl -MData::Dumper -e '@x = ( 1 .. 4 ) ; %y = (x => @x); print Dumper \%y'
$VAR1 = {
          '4' => undef,
          'x' => 1,
          '2' => 3
        };

as seen, it doesn't do what you claim it does. possibly the dump trick
you are using is misleading you. use data::dumper to see what is really
there. here is what you seem to want:

perl -MData::Dumper -e '@x = ( 1 .. 4 ) ; %y = (x => "@x"); print Dumper \%y'
$VAR1 = {
          'x' => '1 2 3 4'
        };


or alternatively with a ref:

perl -MData::Dumper -e '@x = ( 1 .. 4 ) ; %y = (x => \@x); print Dumper \%y'
$VAR1 = {
          'x' => [
                   1,
                   2,
                   3,
                   4
                 ]
        };


uri

-- 
Uri Guttman  ------  uri@stemsystems.com  --------  http://www.sysarch.com --
-----  Perl Code Review , Architecture, Development, Training, Support ------
---------  Gourmet Hot Cocoa Mix  ----  http://bestfriendscocoa.com ---------
0
Reply Uri 6/8/2010 8:38:53 PM

>>>>> "c" == ccc31807  <cartercc@gmail.com> writes:

  c> 'Garbage in, garbage out' isn't always the result of bad code, it
  c> can be the result of bad data. Thanks to all, and please accept my
  c> apology for the excitement.

you still have a bug if you claim x => @y will do what you want. see my
other post on this.

uri

-- 
Uri Guttman  ------  uri@stemsystems.com  --------  http://www.sysarch.com --
-----  Perl Code Review , Architecture, Development, Training, Support ------
---------  Gourmet Hot Cocoa Mix  ----  http://bestfriendscocoa.com ---------
0
Reply Uri 6/8/2010 8:40:04 PM

On Jun 8, 4:40=A0pm, "Uri Guttman" <u...@StemSystems.com> wrote:
> you still have a bug if you claim x =3D> @y will do what you want. see my
> other post on this.

-----------SCRIPT---------------
#! perl
# array.plx
use strict;
use warnings;
my %presidents;
while (<DATA>)
{
	chomp;
	my ($order, $first, $last, @years) =3D split /\|/;
	$presidents{$order} =3D {
		first =3D> $first,
		last =3D> $last,
		years =3D> @years,
	};
}

foreach my $k (sort keys %presidents)
{
	print "$k =3D> $presidents{$k}\n";
	foreach my $k2 (sort keys %{$presidents{$k}})
	{
		print "   $k2 =3D> $presidents{$k}{$k2}\n";
	}
}
exit(0);

__DATA__
1|George|Washington|1788 1792
2|John|Adams|1796
3|Thomas|Jefferson|1800 1804
4|James|Madison|1808 1812
32|Franklin|Roosevelt|1932 1936 1940 1944

----------OUTPUT----------------
D:\PerlLearn>perl array.plx
01 =3D> HASH(0x248e5c)
   first =3D> George
   last =3D> Washington
   years =3D> 1788 1792
02 =3D> HASH(0x182a344)
   first =3D> John
   last =3D> Adams
   years =3D> 1796
03 =3D> HASH(0x182a3b4)
   first =3D> Thomas
   last =3D> Jefferson
   years =3D> 1800 1804
04 =3D> HASH(0x182a8a4)
   first =3D> James
   last =3D> Madison
   years =3D> 1808 1812
32 =3D> HASH(0x183ce44)
   first =3D> Franklin
   last =3D> Roosevelt
   years =3D> 1932 1936 1940 1944
0
Reply ccc31807 6/8/2010 9:12:53 PM

ccc31807 <cartercc@gmail.com> wrote:
> On Jun 8, 4:40 pm, "Uri Guttman" <u...@StemSystems.com> wrote:
>> you still have a bug if you claim x => @y will do what you want. see my
>> other post on this.
>
> -----------SCRIPT---------------
> #! perl
> # array.plx
> use strict;
> use warnings;
> my %presidents;
> while (<DATA>)
> {
> 	chomp;
> 	my ($order, $first, $last, @years) = split /\|/;
> 	$presidents{$order} = {
> 		first => $first,
> 		last => $last,
> 		years => @years,
> 	};
> }

[snip]

> __DATA__
> 1|George|Washington|1788 1792
> 2|John|Adams|1796
> 3|Thomas|Jefferson|1800 1804
> 4|James|Madison|1808 1812
> 32|Franklin|Roosevelt|1932 1936 1940 1944


@years always contains exactly one element, it is a non-arrayish array.

$years would work as well, and would avoid looking like it wouldn't
work...


-- 
Tad McClellan
email: perl -le "print scalar reverse qq/moc.liamg\100cm.j.dat/"
The above message is a Usenet post.
I don't recall having given anyone permission to use it on a Web site.
0
Reply Tad 6/8/2010 9:47:22 PM

On Tue, 08 Jun 2010 14:12:53 -0700, ccc31807 wrote:

> On Jun 8, 4:40 pm, "Uri Guttman" <u...@StemSystems.com> wrote:
>> you still have a bug if you claim x => @y will do what you want. see my
>> other post on this.
> 
> -----------SCRIPT---------------
(snip)
> 	my ($order, $first, $last, @years) = split /\|/; $presidents
{$order} =
> 	{
> 		first => $first,
> 		last => $last,
> 		years => @years,
> 	};
(snip)
> 
> __DATA__
> 1|George|Washington|1788 1792
(snip)

This only "works" because @years has only one element, the string "1788 
1792". It is still wrong, wrong, wrong. Fix your code before someone tags 
on another element on the end and everything breaks.

HTH,
M4
0
Reply Martijn 6/8/2010 9:49:30 PM

Quoth "Uri Guttman" <uri@StemSystems.com>:
> 
> in that limited code i don't see where the keys would be interpreted as
> literal numbers. there must be something else going on which is doing
> that. perl won't lose leading zeroes in strings without doing some
> number conversions. are you sure you never look at those kays as
> numbers? like use == to check them or similar? since they seem to be
> fixed size you can always use the string comparison ops safely.

Comparing with == does no harm. When a scalar has been converted from
string to number, perl remembers that the string value is canonical and
will not lose it. (This is similar to the float/int tricks it does to
keep all the precision possible.)

What *does* do harm is performing arithmetic, or other numeric
operations, and using the result rather than the original. That is:

    my $x = "01";
    $x == 1;
    # $x is still "01"
    $x + 1;
    # $x is still "01"
    $x += 1;
    # $x is now 2, and will stringify as "2"

(this also applies to the redundant case of

    $x += 0;

, which is one of the ways of forcing a scalar to be numeric.)

Ben

0
Reply Ben 6/8/2010 9:52:52 PM

ccc31807 <cartercc@gmail.com> wrote:

>    my ($last, $first, $middle, $id1, $filename, $crs_id, $site, $loc,
> $glcode, $level, $count, $status, $section, $title, $hours, $xlist,
> $total, $travel, $contract) = parse_line(',', 0, $_);
> 	next if $contract =~ /N/;
> 	$sec{$crs_id} = {
> 	crs_id => $crs_id,
> 	filename => $filename,
> 	id1 => $id1,
> 	site => $site,
> 	loc => $loc,
> 	glcode => $glcode,
> 	level => $level,
> 	count => $count,
> 	status => $status,
> 	section => $section,
> 	title => $title,
> 	hours => $hours,
> 	xlist => $xlist,
> 	total => $total,
> 	travel => $travel,
> 	contract => $contract,
> 	};


Hash slice to the rescue! (untested)

    my @fields = qw(
        crs_id
        filename
        id1
        site
        loc
        glcode
        level
        count
        status
        section
        title
        hours
        xlist
        total
        travel
        contract
    );
    @{ $sec{$crs_id} }{@fields} = parse_line(',', 0, $_);
    next if $sec{$crs_id}{contract} =~ /N/;


Look Ma! Each name is typed only once, and there aren't
a bazillion temporary variables!


-- 
Tad McClellan
email: perl -le "print scalar reverse qq/moc.liamg\100cm.j.dat/"
The above message is a Usenet post.
I don't recall having given anyone permission to use it on a Web site.
0
Reply Tad 6/9/2010 12:02:29 AM

On Jun 8, 5:47=A0pm, Tad McClellan <ta...@seesig.invalid> wrote:
> @years always contains exactly one element, it is a non-arrayish array.
>
> $years would work as well, and would avoid looking like it wouldn't
> work...
>

You are right.

As an explanation, not an excuse, the &rest parameter in Lisp takes
the rest of the arguments and flattens all lists. I've found this very
useful in manipulating Lisp data, and guess I was half asleep at the
wheel, channeling Lisp while writing Perl.

What I saw was 'courses' as an array, and in fact use @courses later
on in the script to iterate through the elements, and was thinking
'list' when I should have seen 'scalar.'

My bad, and now I'm triple embarrassed. Uri and the others were
correct, and I wasn't.

CC.
0
Reply ccc31807 6/9/2010 1:00:00 AM

ccc31807 <cartercc@gmail.com> wrote:
>So, I guess my question is how I convert an integer to a string to
>preserve the leading zeros.

There _ARE_NO_ numbers with leading zeros.

A number (no matter if integer or whatever) is an abstract concept and
internally it is represented as whatever binary representation the Perl
interpreter chooses.

If you write down a number then that is no longer a number but a textual
representation, better known as a string.
And if you want to preserve the characteristics of that string, e.g.
leading zeros, then you need to treat that string as a string, not as a
number.

jue
0
Reply J 6/9/2010 1:01:05 AM

ccc31807 <cartercc@gmail.com> wrote:
>I get some of the data in CSV format. One of my sources switched from
>an Access database to an Excel file. Turns out that Excel strips out
>the leading zeros if it thinks that the datum is an integer.

Which I would argue is the correct behaviour for a numerical data field.
If you don't want a canonical numerical form, then declare the data
field to be text. Problem solved.

jue
0
Reply J 6/9/2010 1:08:55 AM

>>>>> "TM" == Tad McClellan <tadmc@seesig.invalid> writes:

  >> my ($order, $first, $last, @years) = split /\|/;
  >> __DATA__
  >> 1|George|Washington|1788 1792
  >> 2|John|Adams|1796
  >> 3|Thomas|Jefferson|1800 1804
  >> 4|James|Madison|1808 1812
  >> 32|Franklin|Roosevelt|1932 1936 1940 1944


  TM> @years always contains exactly one element, it is a non-arrayish array.

  TM> $years would work as well, and would avoid looking like it wouldn't
  TM> work...

gack, i didn't see that! no wonder it 'worked'. i was so caught up in
the wrong use of an array there i didn't notice it was only getting one
value which had the whole string with numbers. he never split that field
into a list of numbers. do'h!!

uri

-- 
Uri Guttman  ------  uri@stemsystems.com  --------  http://www.sysarch.com --
-----  Perl Code Review , Architecture, Development, Training, Support ------
---------  Gourmet Hot Cocoa Mix  ----  http://bestfriendscocoa.com ---------
0
Reply Uri 6/9/2010 1:26:21 AM

Uri Guttman wrote:
>>>>>> "TM" == Tad McClellan <tadmc@seesig.invalid> writes:
> 
>   >> my ($order, $first, $last, @years) = split /\|/;
>   >> __DATA__
>   >> 1|George|Washington|1788 1792
>   >> 2|John|Adams|1796
>   >> 3|Thomas|Jefferson|1800 1804
>   >> 4|James|Madison|1808 1812
>   >> 32|Franklin|Roosevelt|1932 1936 1940 1944
> 
> 
>   TM> @years always contains exactly one element, it is a non-arrayish array.
> 
>   TM> $years would work as well, and would avoid looking like it wouldn't
>   TM> work...
> 
> gack, i didn't see that! no wonder it 'worked'. i was so caught up in
> the wrong use of an array there i didn't notice it was only getting one
> value which had the whole string with numbers. he never split that field
> into a list of numbers. do'h!!

Chuckle. *MY* experience tells me that bugs are never where you're looking ;-)

    BugBear
0
Reply bugbear 6/9/2010 7:57:46 AM

On Jun 8, 9:08=A0pm, J rgen Exner <jurge...@hotmail.com> wrote:
> ccc31807 <carte...@gmail.com> wrote:
> >I get some of the data in CSV format. One of my sources switched from
> >an Access database to an Excel file. Turns out that Excel strips out
> >the leading zeros if it thinks that the datum is an integer.
>
> Which I would argue is the correct behaviour for a numerical data field.
> If you don't want a canonical numerical form, then declare the data
> field to be text. Problem solved.

I get these kinds of files as user input. My supposition is that prior
to this experience, the user was using Access, and configured the ID
field as text (even though it consists entirely of digits), so that
when exported as CSV it kept all seven digits, which it would have
done as a text field, a string.

Users don't normally bother to set the data type of Excel columns
unless they are currency, dates, or specific numeric fields, so Excel
treats a column with numeric characters as numeric, which is entirely
reasonable. When you save the Excel file as CSV, it only saves the
significant digits, not leading zeros. Again, this is entirely
reasonable.

My problem was that I wasn't aware of the switch (might have been told
but wasn't really aware of it) and ASSUMED that the numeric IDs were
all present including the leading zeros. When I figured out that the
errors were associated with the records that had ID consisting of
leading zeros, I ASSUMED that it was a software problem, a bug I had
introduced, a programming error.

As bugbear notes, it was indeed a programming error, but related to
validation of data, not conversion of data types. When I converted the
numeric fields to strings, I got the same error, which ultimately lead
me to examine the data file.

As to use of the @courses variable, I'll change that to $courses. I've
already explained why that happened, and I honestly don't feel too bad
about that, as that's the kind of error we all make when we write in
different languages at the same time.

CC
0
Reply ccc31807 6/9/2010 2:39:33 PM

On 2010-06-08 21:12, ccc31807 <cartercc@gmail.com> wrote:
> #! perl
> # array.plx
> use strict;
> use warnings;
> my %presidents;
> while (<DATA>)
> {
> 	chomp;
> 	my ($order, $first, $last, @years) = split /\|/;
> 	$presidents{$order} = {
> 		first => $first,
> 		last => $last,
> 		years => @years,
> 	};
> }
>
> foreach my $k (sort keys %presidents)
> {
> 	print "$k => $presidents{$k}\n";
> 	foreach my $k2 (sort keys %{$presidents{$k}})
> 	{
> 		print "   $k2 => $presidents{$k}{$k2}\n";
> 	}
> }
> exit(0);

This script never pads $order to two digits.

> __DATA__
> 1|George|Washington|1788 1792
  ^ here $order has only one digit.
> 2|John|Adams|1796
> 3|Thomas|Jefferson|1800 1804
> 4|James|Madison|1808 1812
> 32|Franklin|Roosevelt|1932 1936 1940 1944
>
> ----------OUTPUT----------------
> D:\PerlLearn>perl array.plx
> 01 => HASH(0x248e5c)
  ^^ Thus I do not believe that this output is from the script above.

	hp
0
Reply Peter 6/9/2010 8:00:41 PM

On 2010-06-08 18:26, Uri Guttman <uri@StemSystems.com> wrote:
>>>>>> "c" == ccc31807  <cartercc@gmail.com> writes:
>  c> 0123456 => HASH(deadbeed)
>  c>   id => 0123456
>
> that is an OCTAL literal.

It isn't a literal at all. It's a string read from a file.

	hp

0
Reply Peter 6/9/2010 8:01:46 PM

On Jun 9, 4:00=A0pm, "Peter J. Holzer" <hjp-usen...@hjp.at> wrote:
> On 2010-06-08 21:12, ccc31807 <carte...@gmail.com> wrote:
>
>
>
> > #! perl
> > # array.plx
> > use strict;
> > use warnings;
> > my %presidents;
> > while (<DATA>)
> > {
> > =A0 =A0chomp;
> > =A0 =A0my ($order, $first, $last, @years) =3D split /\|/;
> > =A0 =A0$presidents{$order} =3D {
> > =A0 =A0 =A0 =A0 =A0 =A0first =3D> $first,
> > =A0 =A0 =A0 =A0 =A0 =A0last =3D> $last,
> > =A0 =A0 =A0 =A0 =A0 =A0years =3D> @years,
> > =A0 =A0};
> > }
>
> > foreach my $k (sort keys %presidents)
> > {
> > =A0 =A0print "$k =3D> $presidents{$k}\n";
> > =A0 =A0foreach my $k2 (sort keys %{$presidents{$k}})
> > =A0 =A0{
> > =A0 =A0 =A0 =A0 =A0 =A0print " =A0 $k2 =3D> $presidents{$k}{$k2}\n";
> > =A0 =A0}
> > }
> > exit(0);
>
> This script never pads $order to two digits.
>
> > __DATA__
> > 1|George|Washington|1788 1792
>
> =A0 ^ here $order has only one digit.> 2|John|Adams|1796
> > 3|Thomas|Jefferson|1800 1804
> > 4|James|Madison|1808 1812
> > 32|Franklin|Roosevelt|1932 1936 1940 1944
>
> > ----------OUTPUT----------------
> > D:\PerlLearn>perl array.plx
> > 01 =3D> HASH(0x248e5c)
>
> =A0 ^^ Thus I do not believe that this output is from the script above.
>
> =A0 =A0 =A0 =A0 hp

You are correct. I had copied the script from a previous run and was
playing with the order. The output is from a change in the DATA with
the keys like 01. If you run the script, it produces 1,2, 3, 32, 4.

CC.
0
Reply ccc31807 6/9/2010 8:49:21 PM

31 Replies
576 Views

(page loaded in 0.792 seconds)

Similiar Articles:


















7/24/2012 11:38:36 AM


Reply: