Tweet

Determining length and size

Introduction

Quite often you will want to know the length or size of a variable. It may be a scalar variable, or you may want to know how many elements are in an array or a hash.

Size, or length, can mean a different thing depending on what context you mean. Generally it can mean the number of characters in a string, or the number of elements in an array or hash. However, if you are using Unicode characters the number of characters in a string may be different to the number of bytes in the string.

Example 1. length() and scalar variables

To determine the number of characters in an expression use the length() function:

    #!/usr/bin/perl

    use strict;
    use warnings;

    my $name = 'Bob';

    my $size = length($name);

    print "$size\n";

    exit 0;

This example prints the number of characters in the string $name:

    3

Example 2. length() in bytes

Sometimes you want to know the number of bytes in the string, not the number of characters. This won't affect you for ASCII characters but it may if you are using Unicode characters.

By default the length() function returns the number of characters. You can tell it to return the number of bytes by specifying use bytes;, as in this example:

    #!/usr/bin/perl

    use strict;
    use warnings;

    my $char = "\x{263a}";    # A smiley face

    # Put 'use bytes' in a closure so that it doesn't 
    # affect the rest of the program.  (The 'use bytes' pragma
    # disables character semantics for the rest of the lexical 
    # scope in which it appears).

    {

        use bytes;

        my $byte_size = length($char);

        print "Bytes: $byte_size\n";

    }

    # Character size here
    my $size = length($char);

    print "Chars: $size\n";

    exit 0;

This outputs:

    Bytes: 3
    Chars: 1

Example 3. Arrays: last index

In Perl you can determine the subscript of the last element of an array and add 1 to it to get the number of elements in the array.

    #!/usr/bin/perl

    use strict;
    use warnings;

    my @planets = qw(mercury venus earth mars jupiter);

    my $size = $#planets + 1;

    print "$size\n";

    exit 0;

This gives us:

    5

Example 4. Arrays: scalar context

If you use an array in scalar context, it will return the number of elements in the array:

    #!/usr/bin/perl

    use strict;
    use warnings;

    my @planets = qw(mercury venus earth mars jupiter);

    my $size = @planets;

    print "$size\n";

    exit 0;

This gives us:

    5

Apart from being confusing to read, this method can lead to some easy mistakes. For example, consider the following program:

    #!/usr/bin/perl

    use strict;
    use warnings;

    my @planets = qw(mercury venus earth mars jupiter);

    print "@planets\n";

    exit 0;

What would you expect it to print?

    mercury venus earth mars jupiter

Many functions, double-quotes included, treat arrays differently to scalar variables. The double-quotes cause Perl to flatten the array by concatenating the values into a string.

If you want the number of elements in the array it is best to be explicit about it (see example 6 below).

Example 5. Arrays: don't use length()

If you try to use the length() function on an array, it won't give you the answer you are after:

    #!/usr/bin/perl

    use strict;
    use warnings;

    my @planets = qw(mercury venus earth mars jupiter);

    my $size = length(@planets);

    print "$size\n";

    exit 0;

The output is not what you would expect:

    1

This is because the length() function expects a scalar, so the array is forced into scalar context.

As we saw above (example 4), an array in scalar context already gives us the length. The example above is giving us the length of the length: the length of 5 is 1.

Example 6. Arrays: using scalar()

While example 3 and 4 are correct, they aren't very readable or friendly to use. Perl has the scalar() function which forces the array into scalar context, giving you the length:

    #!/usr/bin/perl

    use strict;
    use warnings;

    my @planets = qw(mercury venus earth mars jupiter);

    my $size = scalar(@planets);

    print "$size\n";

    exit 0;

This also gives us the correct answer:

    5

Example 7. Number of elements in a hash

Sometimes you will also want to know the number of elements in a hash. This is easily done using the keys() function to return the keys as an list, and the scalar() function to return how many keys there are:

    #!/usr/bin/perl

    use strict;
    use warnings;

    my %planet_mass_compared_to_earth = (
        mercury => 0.055,
        venus   => 0.86,
        earth   => 1.0,
        mars    => 0.11,
        jupiter => 318,
    );

    my $size = scalar(keys %planet_mass_compared_to_earth);

    print "$size\n";

    exit 0;

The output of this program is:

    5

Example 8. Finding the memory usage of Perl variables

You can also determine the memory usage in bytes of any variable, including multi-dimensional structures (e.g. a hash of hashes, or an array of arrays, or array of hashes etc). To do this, use the Devel::Size module.

    #!/usr/bin/perl

    use strict;
    use warnings;
    use Devel::Size qw(total_size);

    my %planet_data = (
        1 => {
            name => 'Mercury',
            mass_relative_to_earth  => 0.055,
        },
        2 => {
            name => 'Venus',
            mass_relative_to_earth => 0.86,
        },
        3 => {
            name => 'Earth',
            mass_relative_to_earth => 1.0,
        },
        4 => {
            name => 'Mars',
            mass_relative_to_earth => 0.11,
        },
        5 => {
            name => 'Jupiter',
            mass_relative_to_earth => 318,
        },
    );

    my $total_size = total_size(\%planet_data);

    print "Total Size: $total_size\n";

    exit 0;

On our machine this outputs:

    Total Size: Total Size: 1158

This answer is somewhat system dependent. To get a better understanding of how Devel::Size measures the size of variables, see perldoc Devel::Size.

See also

    perldoc -f length
    perldoc -f scalar
    perldoc bytes
    perldoc Devel::Size
[Top]