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
Re: How to get the TOTAL length/size of an array?
by hippo (Bishop) on Sep 21, 2023 at 09:02 UTC
|
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";
}
| [reply] [d/l] |
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]
| [reply] [d/l] [select] |
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;
| [reply] [d/l] [select] |
|
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
| [reply] [d/l] [select] |
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 string “6” 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,
| [reply] [d/l] [select] |
Re: How to get the TOTAL length/size of an array?
by kcott (Archbishop) on Sep 21, 2023 at 15:22 UTC
|
$ 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.
| [reply] [d/l] [select] |
Re: How to get the TOTAL length/size of an array?
by karlgoethebier (Abbot) on Sep 21, 2023 at 17:51 UTC
|
…
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»
| [reply] [d/l] |
|
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: <%-{-{-{-<
| [reply] [d/l] [select] |
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>
| [reply] [d/l] [select] |
|
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]
| [reply] [d/l] [select] |
|
DB<27> @a=("'");
DB<28> p length(Dumper @a)-2*@a
2
| [reply] [d/l] |
|
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 | [reply] [d/l] [select] |
|
> 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... :)
| [reply] |
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
| [reply] [d/l] |
|
| [reply] |
|
oof shows me to post with one eye shut
| [reply] |
|
|