给定一些字节,它将其格式化为“字节”,“KB”,“MB”或“GB”......但我不明白的是部分:
$_->[1], $_->[0]
不是传递给地图的一组哈希?那么怎么会有一个0和1的索引?
sub fmt {
my $bytes = shift;
return (
sort { length $a <=> length $b }
map { sprintf '%.3g%s', $bytes/1024**$_->[1], $_->[0] }
[" bytes"=>0],[KB=>1],[MB=>2],[GB=>3]
)[0];
}
答案 0 :(得分:7)
这是一段糟糕的代码。有人在炫耀
传递给map
的列表是:匿名数组列表
[ " bytes" => 0 ], [ KB => 1 ], [ MB => 2 ], [ GB => 3 ]
虽然 fat逗号运算符=>
经常出现在哈希文字的上下文中,但这并不是它的全部优点。它与普通逗号,
相同,但 bareword 左手操作数将被隐式引用。如果没有它,列表将与
[ ' bytes', 0 ], [ 'KB', 1 ], [ 'MB', 2 ], [ 'GB', 3 ]
这里有相同的函数,中间map
语句的结果扩展为一个单独的数组@variations
,我使用Data::Dump
转储它以显示它&#39;做
传递给map
的列表是一些匿名数组 - 每个数组都包含后缀字符串以及该字符串对应的1024的相应功率。 return
语句只选择最短的表示
use strict;
use warnings 'all';
use feature 'say';
use Data::Dump;
say fmt(987 * 1024**2);
sub fmt {
my $bytes = shift;
my @variations = map { sprintf '%.3g%s', $bytes/1024 ** $_->[1], $_->[0] }
[ " bytes" => 0 ],
[ KB => 1 ],
[ MB => 2 ],
[ GB => 3 ];
dd \@variations;
return ( sort { length $a <=> length $b } @variations ) [0];
}
["1.03e+009 bytes", "1.01e+006KB", "987MB", "0.964GB"]
987MB
我通常使用类似的东西。 sprintf
的滑稽动作是确保永远不会显示一个字节的分数
sub fmt2 {
my ($n) = @_;
my @suffix = ( '', qw/ K M G T P E / );
my $i = 0;
until ( $n < 1024 or $i == $#suffix ) {
$n /= 1024;
++$i;
}
sprintf $i ? '%.3g%sB' : '%.0f%sB', $n, $suffix[$i];
}
答案 1 :(得分:4)
通过一点点数学,这可以在没有任何迭代或巧妙构造的数组的情况下完成:
my @si_prefix = ('', qw( K M G T P E Z Y ));
sub fmt {
my $bytes = shift or return '0B';
my $pow = int log(abs $bytes)/log(1024);
return sprintf('%3.3g%sB', $bytes / (1024 ** $pow), $si_prefix[$pow]);
}
我们可以使用对数基本更改规则轻松确定1024的最接近功率:log 1024 ($ bytes)= log($ bytes)/ log(1024)
为了好玩,我使用问题代码来运行Benchmark::cmpthese
,@ Borodin fmt2
和我的版本:
Benchmarking 1B
Rate fmt_orig fmt_borodin fmt
fmt_orig 245700/s -- -76% -84%
fmt_borodin 1030928/s 320% -- -34%
fmt 1562500/s 536% 52% --
Benchmarking 7.45GB
Rate fmt_orig fmt_borodin fmt
fmt_orig 224215/s -- -66% -84%
fmt_borodin 653595/s 192% -- -54%
fmt 1428571/s 537% 119% --
Benchmarking 55.5EB
Rate fmt_orig fmt_borodin fmt
fmt_orig 207469/s -- -57% -83%
fmt_borodin 487805/s 135% -- -60%
fmt 1219512/s 488% 150% --
答案 2 :(得分:3)
“不,那些不是哈希。
[" bytes"=>0],[KB=>1],[MB=>2],[GB=>3]
根本不是哈希。 =>
基本上只是一个逗号。所以这是
[" bytes", 0],["KB",1],["MB",2],["GB",3]
这是一种奇怪的方式,因为它有点构造哈希。
所以我写的更像是:
sub fmt2 {
my ($bytes) = @_;
my @units = qw ( bytes KB MB GB TB );
#divide by 1024 whilst above
while ( $bytes > 1024 ) {
shift(@units); #drop one of the units prefixes until one 'fits'.
$bytes /= 1024;
}
return sprintf( '%.3g%s', $bytes, $units[0] );
}
答案 3 :(得分:1)
不,它没有传递哈希数组。它正在传递一个数组引用列表,其中每个引用的数组恰好包含两个元素。
Perl中的=>
运算符也称为&#34; fat逗号&#34;运营商。它与,
运算符相同,只是它会自动引用左手参数。它最常用于散列和散列引用,因为键通常是字符串,并且对于以某种方式链接键和值的可视指示很有用,但这不是必需的。
[" bytes"=>0],[KB=>1],[MB=>2],[GB=>3]
与
完全相同 [" bytes", 0],['KB', 1],['MB', 2],['GB', 3]
仅使用=>
而不是,
运算符不会将双元素数组转换为哈希值。如果您想传递map
哈希引用列表,则必须将所有[ ]
更改为{ }
{" bytes"=>0},{KB=>1},{MB=>2},{GB=>3}
答案 4 :(得分:0)
map { sprintf '%.3g%s', $bytes/1024**$_->[1], $_->[0] } [" bytes"=>0],[KB=>1],[MB=>2],[GB=>3]
上面的部分返回一个用sprintf()
格式化的字符串列表。
$_->[1]
代表&#34;右边的数字。 bytes&#34;,KB,MB等,而$_->[0]
代表&#34; bytes&#34;,KB,MB等字符串
整个函数返回在用sprintf()
格式化的所有格式中具有最大长度的字符串。