如何用前导零填充值?

IT技术 javascript zerofill
2021-01-10 19:31:25

在 JavaScript 中对值进行零填充的推荐方法是什么?我想我可以构建一个自定义函数来将零填充到类型转换值上,但我想知道是否有更直接的方法来做到这一点?

注意:我所说的“zerofilled”是指这个词的数据库意义(其中数字 5 的 6 位零填充表示将是“000005”)。

6个回答

我无法相信这里所有复杂的答案......只需使用这个:

var zerofilled = ('0000'+n).slice(-4);
@OmShankar 通过“复杂的答案”,我指的不是解释或详细的答案(尽管我的答案不是),但本网站显然鼓励这样做),而是包含不必要的代码复杂性的答案。
2021-03-14 19:31:25
@wberry 这并不是要成为生产就绪的代码,而是对解决手头问题的基础知识的简单解释。也就是很容易确定一个数字是正数还是负数,并在需要时添加适当的符号,所以我不想将我的简单示例与它聚集在一起。此外,制作一个将数字长度作为参数并使用它而不是我的硬编码值的函数也很容易。
2021-03-24 19:31:25
除了负数和超过 4 位的数字外,很好。
2021-04-01 19:31:25
@Seaux,你说:“无法相信所有复杂的答案”,然后在评论时开始解释自己的复杂性。这意味着您了解从某些角度来看,您的答案并不完美。因此复杂性。
2021-04-04 19:31:25
我喜欢这个答案。在我自己的特定情况下,我知道数字始终为正数且不会超过 3 位数,当您使用前导 0 进行填充并且您的输入众所周知时,通常就是这种情况。好的!
2021-04-04 19:31:25

简单的方法。您可以为打击垫添加字符串乘法并将其转换为函数。

var pad = "000000";
var n = '5';
var result = (pad+n).slice(-pad.length);

作为一个函数,

function paddy(num, padlen, padchar) {
    var pad_char = typeof padchar !== 'undefined' ? padchar : '0';
    var pad = new Array(1 + padlen).join(pad_char);
    return (pad + num).slice(-pad.length);
}
var fu = paddy(14, 5); // 00014
var bar = paddy(2, 4, '#'); // ###2
@BrockAdams,zerofill 通常用于固定宽度的数字/格式情况——因此我认为如果在尝试进行 2 位 zerofill 时给出 3 位数字,它实际上不太可能(甚至不是问题)。
2021-03-13 19:31:25
("000000" + somenum).substr(-6,6) 其中零的数量和 -6,6 对应于焊盘宽度。同样的想法,但 slice 少了一个参数;不确定切片是比 subtr 快还是慢。当然,我的解决方案不需要变量赋值。
2021-03-24 19:31:25
这是一个非常好的解决方案,是我见过的最好的解决方案。为了清楚起见,这里有一个更简单的版本,我用它来填充时间格式的分钟:('0'+minutes).slice(-2)
2021-03-31 19:31:25
这有一个致命的缺陷,比预期的数字大——这是一种非常常见的情况。例如,paddy (888, 2)产量88并没有888达到要求。这个答案也不处理负数。
2021-04-02 19:31:25
这比使用 while 循环的实现慢 5 倍:gist.github.com/4382935
2021-04-05 19:31:25

读者注意!

正如评论者指出的那样,这个解决方案是“聪明的”,而且通常是聪明的解决方案,它是内存密集型的并且相对较慢。如果您关心性能,请不要使用此解决方案!

可能已过时:ECMAScript 2017 包括String.prototype.padStartNumber.prototype.toLocaleString自 ECMAScript 3.1 以来就存在。例子:

var n=-0.1;
n.toLocaleString('en', {minimumIntegerDigits:4,minimumFractionDigits:2,useGrouping:false})

...将输出“-0000.10”。

// or 
const padded = (.1+"").padStart(6,"0");
`-${padded}`

...将输出“-0000.1”。

一个简单的功能就是你所需要的

function zeroFill( number, width )
{
  width -= number.toString().length;
  if ( width > 0 )
  {
    return new Array( width + (/\./.test( number ) ? 2 : 1) ).join( '0' ) + number;
  }
  return number + ""; // always return a string
}

如果你想保存命名空间或其他什么,你可以将它烘焙到一个库中。就像jQuery 的扩展一样

不是每次想要填充值时都创建新数组的粉丝。读者应该意识到潜在的内存和 GC 影响,如果他们正在执行这些操作中的大量 #(例如,在每秒执行 1000 次这些操作的 node.js 服务器上。@profitehlolz 的答案似乎是更好的解决方案.)
2021-03-10 19:31:25
从 ECMAScript 2017 开始,有一个内置函数padStart
2021-03-15 19:31:25
此处三个最佳答案中的性能测量:jsperf.com/left-zero-pad
2021-03-22 19:31:25
这不适用于负值: zeroFill(-10, 7) -> "0000-10"
2021-03-23 19:31:25
现在你只需要处理像 50.1234 这样的数字,你就有了下面我的解决方案的可读版本!然而,我确实假设我们只是左填充,而不是整体填充。
2021-03-24 19:31:25

我实际上最近不得不想出这样的东西。我认为必须有一种方法可以在不使用循环的情况下做到这一点。

这就是我想出的。

function zeroPad(num, numZeros) {
    var n = Math.abs(num);
    var zeros = Math.max(0, numZeros - Math.floor(n).toString().length );
    var zeroString = Math.pow(10,zeros).toString().substr(1);
    if( num < 0 ) {
        zeroString = '-' + zeroString;
    }

    return zeroString+n;
}

然后只需使用它提供一个数字到零填充:

> zeroPad(50,4);
"0050"

如果数字大于填充,则数字将扩展到填充之外:

> zeroPad(51234, 3);
"51234"

小数也可以!

> zeroPad(51.1234, 4);
"0051.1234"

如果不介意污染全局命名空间,可以直接将其添加到 Number 中:

Number.prototype.leftZeroPad = function(numZeros) {
    var n = Math.abs(this);
    var zeros = Math.max(0, numZeros - Math.floor(n).toString().length );
    var zeroString = Math.pow(10,zeros).toString().substr(1);
    if( this < 0 ) {
        zeroString = '-' + zeroString;
    }

    return zeroString+n;
}

如果您希望小数在填充中占据空间:

Number.prototype.leftZeroPad = function(numZeros) {
    var n = Math.abs(this);
    var zeros = Math.max(0, numZeros - n.toString().length );
    var zeroString = Math.pow(10,zeros).toString().substr(1);
    if( this < 0 ) {
        zeroString = '-' + zeroString;
    }

    return zeroString+n;
}

干杯!



XDR提出了一个似乎表现更好的对数变化

警告:如果 num 等于零(例如 zeropad(0, 2)),此函数将失败

function zeroPad (num, numZeros) {
    var an = Math.abs (num);
    var digitCount = 1 + Math.floor (Math.log (an) / Math.LN10);
    if (digitCount >= numZeros) {
        return num;
    }
    var zeroString = Math.pow (10, numZeros - digitCount).toString ().substr (1);
    return num < 0 ? '-' + zeroString + an : zeroString + an;
}

说到性能,tomsmeding 比较了前 3 个答案4 个与对数变化)。猜猜哪一个主要优于其他两个?:)

+1。与更高投票的答案不同,这个答案处理负数并且不会在溢出时返回严重错误!?!
2021-03-12 19:31:25
我通过使用对数将这个答案的性能提高了 100% 以上。请参阅http://jsperf.com/left-zero-pad/10 上的对数测试用例
2021-03-23 19:31:25
此处三个最佳答案中的性能测量:jsperf.com/left-zero-pad
2021-03-27 19:31:25
这很好,我喜欢它的可读性和健壮性。我唯一要更改的是numZeros参数的名称,因为它具有误导性。这不是您要添加的零的数量,而是数字应为的最小长度。更好的名字是numLength甚至length.
2021-04-02 19:31:25
原始解决方案更好,如果num可以为零,则对数变化不起作用......
2021-04-04 19:31:25

这是我用来填充最多 7 个字符的数字。

("0000000" + number).slice(-7)

对于大多数人来说,这种方法可能就足够了。

编辑:如果你想让它更通用,你可以这样做:

("0".repeat(padding) + number).slice(-padding)

编辑 2:请注意,从 ES2017 开始,您可以使用String.prototype.padStart

number.toString().padStart(padding, "0")
抱歉,我应该提到这不适用于负数。不过,我认为这涉及更常见的正数情况。它至少可以满足我的需求!
2021-03-24 19:31:25
很好的解决方案 padStart()
2021-03-27 19:31:25
(new Array(padding + 1).join("0") 可以替换为 "0".repeat(padding)
2021-03-28 19:31:25
这在大数和负数上都失败了。 number = 123456789,例如上面的代码。
2021-04-03 19:31:25
对于某些情况,此解决方案是有史以来最好的解决方案!我不知道为什么我们之前没有想出这个。情况是:您有一个始终为正数的数字 [如 Brock 提到的那样],并且您知道它不会占用超过您的限制的字符数。在我们的例子中,我们有一个存储在 Amazon SDB 中的分数。如您所知,SDB 无法比较数字,因此所有分数都必须补零。这是非常简单和有效的!
2021-04-07 19:31:25