Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

How to get the TOTAL length/size of an array?

by Polyglot (Chaplain)
on Sep 21, 2023 at 04:40 UTC ( #11154560=perlquestion: print w/replies, xml ) Need Help??

Polyglot has asked for the wisdom of the Perl Monks concerning the following question:

PerlMaven has an interesting example that is short by one additional array characterization--one which I have searched for online in vain. Here is his example:

my $one_string = "hello world"; say length $one_string; # 11 my @many_strings = ("abc", "cd", "e", "fg", "hi", "hello world"); say length @many_strings; # 1 say scalar @many_strings; # 6

I want to know what it would take for the next one:

say __?__ @many_strings; # 21

Blessings,

~Polyglot~

Replies are listed 'Best First'.
Re: How to get the TOTAL length/size of an array?
by hippo (Bishop) on Sep 21, 2023 at 09:02 UTC

    TIMTOWTDI

    use strict; use warnings; use Test::More tests => 3; my @many_strings = ("abc", "cd", "e", "fg", "hi", "hello world"); my $want = 21; is length (join '', @many_strings), $want, "length join"; { local $" = ''; is length "@many_strings", $want, "length interpolation"; } { my $len = 0; $len += length for @many_strings; is $len, $want, "sum over length loop"; }

    🦛

Re: How to get the TOTAL length/size of an array?
by choroba (Cardinal) on Sep 21, 2023 at 09:01 UTC
    Interestingly, using length join is pretty fast:
    #!/usr/bin/perl use warnings; use strict; use List::Util qw{ sum }; use Benchmark qw{ cmpthese }; use Test::More tests => 1; my @arr = ('abc', 'cd', 'e', 'fg', 'hi', 'hello world'); sub xsum { sum(map length, @arr) } sub xjoin { length join "", @arr } warn xsum(); is xsum(), xjoin(), 'same'; cmpthese(-3, { sum => \&xsum, join => \&xjoin, });

    Output:

    1..1 21 at ./2.pl line 14. ok 1 - same Rate sum join sum 1470509/s -- -77% join 6267577/s 326% --

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re: How to get the TOTAL length/size of an array?
by swl (Parson) on Sep 21, 2023 at 05:02 UTC
    my $len; $len += length $_ for @many_strings; say $len;
    or:
    use List::Util qw/sum/; say sum map {length $_} @many_strings;

    Edit: Or, as documented in List::Util:

    use List::Util qw /reduce/; say reduce { $a + length $b } 0, @many_strings;

      use List::Util qw /reduce/; say reduce { $a + length $b } 0, @many_strings;

      For cheap thrills, I browsed List::MoreUtils but nothing jumped out at me. This one is similar to yours (both programs produce 21):

      use v5.38; use List::MoreUtils qw/reduce_0/; my @many_strings = ("abc", "cd", "e", "fg", "hi", "hello world"); say reduce_0 { $a + length $b } @many_strings;

      I'm always out-classed by tybalt89 in these kinds of challenges, so I look forward to seeing what concoctions he comes up with when the USA time zone kicks in. :)

      List Utils Modules

      Updated: added "List Utils Modules" section

Re: How to get the TOTAL length/size of an array?
by Athanasius (Archbishop) on Sep 21, 2023 at 07:39 UTC
    say length @many_strings; # 1

    I think it should be pointed out that in this statement, length puts @many_strings into scalar context, thereby yielding 6 (as shown explicitly in the following line), and then 1 is returned because the length of the string6” happens to be 1. With warnings enabled, this gives a warning, as it should:

    17:09 >perl -wE "my @many_strings = ('abc', 'cd', 'e', 'fg', 'hi', 'he +llo world'); say length @many_strings;" length() used on @many_strings (did you mean "scalar(@many_strings)"?) + at -e line 1. 1 17:29 >

    For the record, in Raku swl’s use of reduce could be written:

    use v6d; my Str @many-strings = |<abc cd e fg hi>, 'hello world'; @many-strings.raku.put; @many-strings.elems.put; say [+] @many-strings.map: { .chars };

    Output:

    17:09 >raku 2090_SoPW.raku Array[Str].new("abc", "cd", "e", "fg", "hi", "hello world") 6 21 17:09 >

    using Raku’s built-in reduction metaoperator [+], documented here.

    Hope that’s of interest,

    Athanasius <°(((><contra mundum סתם עוד האקר של פרל,

Re: How to get the TOTAL length/size of an array?
by kcott (Archbishop) on Sep 21, 2023 at 15:22 UTC

    G'day Polyglot,

    TMTOWTDI

    $ perl -E ' my @many_strings = ("abc", "cd", "e", "fg", "hi", "hello world"); $" = ""; say length "@many_strings"; ' 21

    Although, I'd generally localise changes to special variables in the smallest scope possible:

    $ perl -E ' my @many_strings = ("abc", "cd", "e", "fg", "hi", "hello world"); { local $" = ""; say length "@many_strings"; } ' 21

    Update: I checked to see if anyone had used that prior to posting. Obviously, I didn't look closely enough: after posting I noticed ++hippo had already posted the same solution.

    — Ken

Re: How to get the TOTAL length/size of an array?
by karlgoethebier (Abbot) on Sep 21, 2023 at 17:51 UTC

    Variety delights:

    … my @l = ("abc", "cd", "e", "fg", "hi", "hello world"); say length pack("A*" x scalar @l, @l); __END__ karl@h3002993:~/src/perl$ ./pack.pl 21

    «The Crux of the Biscuit is the Apostrophe»

      With slightly fewer manipulations:

      Win8 Strawberry 5.8.9.5 (32) Thu 09/21/2023 16:18:12 C:\@Work\Perl\monks >perl -wMstrict -le " my @l = ('abc', 'cd', 'e', 'fg', 'hi', 'hello world'); print length pack '(A*)*', @l;" 21


      Give a man a fish:  <%-{-{-{-<

Re: How to get the TOTAL length/size of an array?
by LanX (Saint) on Sep 21, 2023 at 18:59 UTC
    The title of your question is misleading, because you want the total number of characters of an array of strings

    An array has only the "size" of scalar @array because in reality the members are only pointers to scalars.

    But a scalar can be a reference to an even deeper data structure.

    The correct answer would hence be using Devel::Size to get the total memory of a deep data structure.

    If you only want the total length of characters of a deep data structure, you can (ab)use serializers Data::Dumper or similar for an approximation, with the benefit that this would "work" for more deeply nested structures too

    edit DEMO

    DB<20> use Data::Dumper DB<21> @a=("abc", "cd", "e", "fg", "hi", "hello world"); DB<23> $Data::Dumper::Terse = 1 DB<24> $Data::Dumper::Indent = 0 DB<25> p Dumper @a 'abc''cd''e''fg''hi''hello world' DB<26> p length(Dumper @a)-2*@a 21 DB<27>

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    see Wikisyntax for the Monastery

      Doesn't work if the strings contain a backslash.
      @a = ('a\\b'); print length(Dumper @a)-2*@a; # 4

      map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
        well I've said approximation and did put "work" in quotes.

        But granted I had other problems in mind than backslashes...

        edit

        also single quotes;

        DB<27> @a=("'"); DB<28> p length(Dumper @a)-2*@a 2

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        see Wikisyntax for the Monastery

      I totally agree with this The title of your question is misleading, because you want the total number of characters of an array of strings

      But this is misleading or could be better phrased:  The correct answer would hence be using Devel::Size to get the total memory of a deep data structure. Unless I misunderstood and by correct answer you mean to some other question!

      The (total) number of characters in a deep structure (e.g. polyglot's array of strings) has nothing to do with the size of memory it uses (as in "space in RAM" etc.) except that when one increases the other increases and vice versa. In C it is even worse because of memory alignment when storing etc.

      Consider this:

      use Devel::Size qw(size total_size); print size("A string"); 42

      bw, bliako

        > But this is misleading or could be better phrased: The correct answer would hence be using Devel::Size to get the total memory of a deep data structure. Unless I misunderstood and by correct answer you mean to some other question!

        I rephrase, the most sensible answer to a general "TOTAL length/size of an array" is memory consumption measured by Devel::Size. Anything else is a matter of interpretation and lengthy definitions in the question.

        > has nothing to do with the size of memory it uses

        well in the case of strings it's roughly proportional. Maybe mostly off by 10% in average.

        And yes, I was nitpicking... :)

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        see Wikisyntax for the Monastery

Re: How to get the TOTAL length/size of an array?
by perlfan (Vicar) on Sep 21, 2023 at 12:51 UTC
    Not sure how he did it. Here's another way.
    use strict; use warnings; use v5.10; my @many_strings = (qw/the slow orange fox did something yada yada yad +a/); sub this (@) { return scalar @_; } say this @many_strings; # 21

      That code counts the number of words in the list, and not the characters. It returns 9, not 21.


      The way forward always starts with a minimal test.
        oof shows me to post with one eye shut

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11154560]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (5)
As of 2023-11-29 08:56 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?