给定了一些字节,它将其格式化为"字节","KB","MB"或"GB"......但我不明白的是部分:
$_->[1], $_->[0]
Run Code Online (Sandbox Code Playgroud)
是不是传递给地图只是一个哈希数组?那么如何才能有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];
}
Run Code Online (Sandbox Code Playgroud)
这是一段糟糕的代码.有人在炫耀
传递给的列表map是这样的:匿名数组列表
[ " bytes" => 0 ], [ KB => 1 ], [ MB => 2 ], [ GB => 3 ]
Run Code Online (Sandbox Code Playgroud)
虽然胖逗号运算符=>经常出现在哈希文字的上下文中,但这并不是一件好事.除了裸字左手操作数将被隐式引用之外,它与普通逗号,相同.没有它,列表将是相同的
[ ' bytes', 0 ], [ 'KB', 1 ], [ 'MB', 2 ], [ 'GB', 3 ]
Run Code Online (Sandbox Code Playgroud)
这是相同的函数,中间map语句的结果扩展为一个单独的数组@variations,我转储Data::Dump它以显示它正在做什么
传递给的列表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];
}
Run Code Online (Sandbox Code Playgroud)
["1.03e+009 bytes", "1.01e+006KB", "987MB", "0.964GB"]
987MB
Run Code Online (Sandbox Code Playgroud)
我通常使用类似的东西.滑稽动作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];
}
Run Code Online (Sandbox Code Playgroud)
只需一点数学知识,无需任何迭代或巧妙构造的数组即可完成此操作:
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]);
}
Run Code Online (Sandbox Code Playgroud)
我们可以通过使用对数基数变化规则轻松确定最接近的 1024 次方: log 1024 ($bytes) = log($bytes) / log(1024)
只是为了好玩,我Benchmark::cmpthese使用问题 @Borodin'sfmt2和我的版本中的代码运行:
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% --
Run Code Online (Sandbox Code Playgroud)