ฉันจะ pad ค่าด้วยศูนย์นำหน้าได้อย่างไร


394

วิธีที่แนะนำในการเติมค่าใน JavaScript คืออะไร? ฉันคิดว่าฉันสามารถสร้างฟังก์ชั่นที่กำหนดเองเพื่อวางค่าศูนย์ลงบนค่า typecasted แต่ฉันสงสัยว่ามีวิธีที่ตรงกว่านี้หรือไม่?

หมายเหตุ:โดย "zerofilled" ฉันหมายถึงในความหมายฐานข้อมูลของคำ (โดยที่การแสดงตัวเลข zerofilled 6 หลักของหมายเลข 5 จะเป็น "000005")


ข้อมูลนี้ไม่เพียงพอที่จะตอบ อินสแตนซ์ที่พบบ่อยที่สุดของ "zero padding" อาจเป็นไปได้ที่จะเตรียมเลขศูนย์ไปยังวันที่: 5/1/2008> 05/01/2008 นั่นคือสิ่งที่คุณหมายถึงอะไร
Triptych

6
สำหรับแอปโหนดให้ใช้npm install sprintf-jsและจำเป็นต้องใช้ในไฟล์ที่คุณต้องการ:sprintf('%0d6', 5);
Droogans

function padWithZeroes(n, width) { while(n.length<width) n = '0' + n; return n;} ... สมมติว่าnไม่ใช่ลบ
เปาโล

@ เปาโลฟังก์ชั่นนั้นใช้ไม่ได้ถ้า n เป็นตัวเลข คุณจะต้องแปลง n เป็น String ก่อนwhileเพื่อให้สามารถเข้าถึงn.length
Nick F

1
ซับหนึ่งที่ไม่มีคณิตศาสตร์หรือในขณะที่ลูปหรือไลบรารี? mynum = "0".repeat((n=6-mynum.toString().length)>0?n:0)+mynum;
Adam Whateverson

คำตอบ:


225

หมายเหตุถึงผู้อ่าน!

ตามที่นักวิจารณ์ได้ชี้ให้เห็นวิธีแก้ปัญหานี้คือ "ฉลาด" และเนื่องจากวิธีแก้ปัญหาที่ชาญฉลาดมักเป็นเพราะหน่วยความจำค่อนข้างเข้มข้นและค่อนข้างช้า หากประสิทธิภาพเป็นสิ่งที่คุณกังวลอย่าใช้โซลูชันนี้!

ล้าสมัยที่อาจเกิดขึ้น : ECMAScript 2017 ประกอบด้วย String.prototype.padStartและ Number.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 ขยาย


1
ตอนนี้คุณแค่ต้องดูแลตัวเลขเช่น 50.1234 และคุณมีโซลูชันของฉันที่อ่านได้ด้านล่าง! อย่างไรก็ตามฉันคิดว่าเราเหลือช่องว่างภายในไม่ใช่ช่องว่างภายในโดยรวม
coderjoe

7
ไม่ใช่แฟนของการสร้างอาร์เรย์ใหม่ทุกครั้งที่คุณต้องการรองค่า ผู้อ่านควรตระหนักถึงหน่วยความจำที่อาจเกิดขึ้นและผลกระทบ GC หากพวกเขากำลังทำสิ่งเหล่านี้เป็นจำนวนมาก (เช่นบนเซิร์ฟเวอร์ node.js ที่กำลังดำเนินการ 1,000 รายการต่อวินาที @ คำตอบของ profitehlolz ดูเหมือนจะเป็นทางออกที่ดีกว่า .)
broofa

6
สิ่งนี้ไม่สามารถใช้กับค่าลบ: zeroFill (-10, 7) -> "0000-10"
digitalbath

2
การวัดประสิทธิภาพของคำตอบสามอันดับแรกที่นี่: jsperf.com/left-zero-pad
tomsmeding

12
ตั้งแต่วันที่ ECMAScript 2017 มีpadStart ของฟังก์ชันในตัว
Tomas Nikodym

321

วิธีง่ายๆ คุณสามารถเพิ่มการคูณสตริงสำหรับแผ่นและเปลี่ยนเป็นฟังก์ชั่น

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

95
นี่เป็นทางออกที่ดีมากที่ดีที่สุดที่ฉันเคยเห็น เพื่อความชัดเจนนี่เป็นเวอร์ชันที่เรียบง่ายกว่าที่ฉันใช้ในการจัดรูปแบบนาทีในรูปแบบ: ('0' + นาที) .slice (-2)
ลุคเอชเรสแมน

17
ซึ่งช้ากว่าการใช้งาน 5 เท่าด้วยขณะที่วนรอบ: gist.github.com/4382935
andrewrk

42
นี่เป็นFATAL FLAW ที่มีตัวเลขมากกว่าที่คาดไว้ซึ่งเป็นเหตุการณ์ที่เกิดขึ้นบ่อยมาก ตัวอย่างเช่นpaddy (888, 2)ผลผลิต88และไม่888เป็นไปตามที่ต้องการ คำตอบนี้ไม่ได้จัดการกับจำนวนลบ
Brock Adams

8
@ RockAdams โดยทั่วไปแล้ว zerofill จะใช้สำหรับกรณีจำนวน / การจัดรูปแบบความกว้างคงที่ - ดังนั้นฉันคิดว่ามันน่าจะเป็นไปได้น้อยลง
Seaux

1
("000000" + somenum) .substr (-6,6) โดยที่จำนวนศูนย์และ -6,6 สอดคล้องกับความกว้างของแผ่น ความคิดเดียวกัน แต่ชิ้นใช้เวลาน้อยหนึ่ง param; ไม่แน่ใจว่าชิ้นเร็วกว่าหรือช้ากว่า subtr แน่นอนว่าโซลูชันของฉันไม่ต้องการการกำหนดตัวแปร
slartibartfast

315

ฉันไม่อยากจะเชื่อคำตอบที่ซับซ้อนทั้งหมดที่นี่ ... แค่ใช้สิ่งนี้:

var zerofilled = ('0000'+n).slice(-4);

27
ดียกเว้นตัวเลขและตัวเลขติดลบที่ยาวเกิน 4 หลัก
wberry

12
@wberry นี่ไม่ได้มีวัตถุประสงค์เพื่อเป็นรหัสพร้อมการผลิต แต่เพิ่มเติมคำอธิบายง่ายๆของพื้นฐานในการแก้ปัญหาที่อยู่ในมือ Aka มันง่ายมากที่จะตรวจสอบว่าจำนวนเป็นบวกหรือลบและเพิ่มเครื่องหมายที่เหมาะสมหากจำเป็นดังนั้นฉันไม่ต้องการจัดกลุ่มตัวอย่างง่าย ๆ ของฉันกับสิ่งนั้น นอกจากนี้มันเป็นเรื่องง่ายที่จะทำให้ฟังก์ชั่นมีความยาวเป็นดิจิตัลและใช้แทนค่าฮาร์โค้ดของฉัน
Seaux

5
@Seaux คุณพูดว่า: "ไม่สามารถเชื่อคำตอบที่ซับซ้อนทั้งหมด"แล้วเริ่มอธิบายความซับซ้อนของตัวเองเมื่อแสดงความคิดเห็น ซึ่งหมายความว่าคุณเข้าใจว่ามีมุมมองที่คำตอบของคุณไม่สมบูรณ์ ดังนั้นความซับซ้อน
Om Shankar

2
@OmShankar โดย "คำตอบที่ซับซ้อน" ฉันไม่ได้อ้างถึงคำตอบที่อธิบายหรือรายละเอียด (ซึ่งได้รับการสนับสนุนอย่างชัดเจนในเว็บไซต์นี้แม้ว่าคำตอบของฉันจะไม่ได้) แต่เป็นคำตอบที่มีความซับซ้อนของรหัสที่ไม่จำเป็น
Seaux

7
ฉันชอบคำตอบนี้ ในกรณีเฉพาะของฉันเองฉันรู้ว่าตัวเลขนั้นเป็นค่าบวกเสมอและไม่เกิน 3 หลักและนี่ก็เป็นกรณีที่เมื่อคุณเติมด้วย 0 นำหน้าและข้อมูลของคุณเป็นที่รู้จักกันดี ดี!
Patrick Chu

110

จริง ๆ แล้วฉันต้องคิดอะไรแบบนี้ ฉันคิดว่าต้องมีวิธีที่จะทำโดยไม่ต้องใช้ลูป

นี่คือสิ่งที่ฉันมาด้วย

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 กับรูปแบบบันทึก ) เดาที่หนึ่งmajorlyเฮงอีกสอง? :)


9
นี่เป็นสิ่งที่ดีฉันชอบวิธีที่อ่านได้และมีประสิทธิภาพ สิ่งเดียวที่ฉันจะเปลี่ยนคือชื่อของnumZerosพารามิเตอร์เนื่องจากมันทำให้เข้าใจผิด ไม่ใช่จำนวนศูนย์ที่คุณต้องการเพิ่มมันคือความยาวต่ำสุดที่ควรเป็น ชื่อที่ดีกว่าจะหรือแม้กระทั่งnumLength length
มีความรู้สึก

13
+1 ซึ่งแตกต่างจากคำตอบที่ได้รับการโหวตสูงกว่าคนนี้จัดการกับจำนวนลบและจะไม่ส่งกลับข้อผิดพลาดในการล้น !!
เบอร์ทรัมอดัมส์

10
การวัดประสิทธิภาพของคำตอบสามอันดับแรกที่นี่: jsperf.com/left-zero-pad
tomsmeding

4
ฉันปรับปรุงประสิทธิภาพของคำตอบนี้มากกว่า 100% โดยใช้ลอการิทึม โปรดดูกรณีทดสอบลอการิทึมที่http://jsperf.com/left-zero-pad/10
XDR

2
วิธีแก้ปัญหาดั้งเดิมดีกว่ารูปแบบลอการิทึมไม่ทำงานหากnumสามารถเป็นศูนย์ ...
Ondra C.

69

นี่คือสิ่งที่ฉันใช้ในการวางตัวเลขได้สูงสุด 7 ตัวอักษร

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

วิธีนี้อาจเพียงพอสำหรับคนส่วนใหญ่

แก้ไข: หากคุณต้องการทำให้เป็นเรื่องทั่วไปคุณสามารถทำสิ่งนี้ได้:

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

แก้ไข 2: โปรดทราบว่าตั้งแต่ ES2017 คุณสามารถใช้String.prototype.padStart:

number.toString().padStart(padding, "0")

สิ่งนี้ล้มเหลวไม่ดีสำหรับจำนวนมากและจำนวนลบ number = 123456789ตัวอย่างเช่นด้วยโค้ดด้านบน
เบอร์ทรัมอดัมส์

วิธีนี้เป็นวิธีที่ดีที่สุดเท่าที่เคยมีมาสำหรับสถานการณ์ที่แน่นอน! ฉันไม่รู้เลยว่าทำไมเราไม่เคยคิดเรื่องนี้มาก่อน สถานการณ์คือ: คุณมีตัวเลขที่เป็นค่าบวกเสมอ [ตามที่ Brock กล่าวไว้] และคุณรู้ว่าจะไม่ใช้อักขระเกินขีด จำกัด ของคุณ ในกรณีของเราเรามีคะแนนที่เราเก็บไว้ใน Amazon SDB อย่างที่คุณทราบ SDB ไม่สามารถเปรียบเทียบตัวเลขได้ดังนั้นคะแนนทั้งหมดจะต้องเป็นศูนย์ มันง่ายมากและมีประสิทธิภาพ!
Krystian

4
ขอโทษฉันควรได้กล่าวว่าสิ่งนี้จะไม่ทำงานสำหรับตัวเลขลบ ฉันคิดว่าข้อตกลงนี้เกี่ยวข้องกับตัวพิมพ์เลขบวกทั่วไปมากกว่า มันทำในสิ่งที่ฉันต้องการอย่างน้อย!
chetbox

new Stringจำเป็นนี้อีกครั้งและตระหนักถึงคุณไม่จำเป็นต้อง คุณสามารถใช้ตัวอักษรสตริง
chetbox

3
(new Array(padding + 1).join("0")สามารถแทนที่ด้วย"0".repeat(padding)
Pavel

34

เบราว์เซอร์สมัยใหม่รองรับในขณะนี้padStartคุณสามารถทำได้ดังนี้:

string.padStart(maxLength, "0");

ตัวอย่าง:

string = "14";
maxLength = 5; // maxLength is the max string length, not max # of fills
res = string.padStart(maxLength, "0");
console.log(res); // prints "00014"


@Flimm รู้สึกอิสระที่จะแก้ไขมันลงในคำตอบ :) มันถูกเขียนเมื่อ 4 ปีที่แล้วดังนั้นฉันจึงมั่นใจว่าตอนนี้สิ่งต่าง ๆ ได้เปลี่ยนไปแล้ว
สเตอร์ลิงอาร์เชอร์

27

น่าเสียดายที่มีคำแนะนำที่ซับซ้อนที่ไม่จำเป็นสำหรับปัญหานี้โดยทั่วไปแล้วเกี่ยวข้องกับการเขียนฟังก์ชันของคุณเพื่อทำการคำนวณทางคณิตศาสตร์หรือการจัดการสตริงหรือการเรียกยูทิลิตี้ของบุคคลที่สาม อย่างไรก็ตามมีวิธีการมาตรฐานในการทำเช่นนี้ในไลบรารี JavaScript พื้นฐานโดยมีโค้ดเพียงบรรทัดเดียว มันอาจคุ้มค่าที่จะรวมโค้ดหนึ่งบรรทัดในฟังก์ชันเพื่อหลีกเลี่ยงการระบุพารามิเตอร์ที่คุณไม่ต้องการเปลี่ยนเช่นชื่อโลคัลหรือสไตล์

var amount = 5;

var text = amount.toLocaleString('en-US',
{
    style: 'decimal',
    minimumIntegerDigits: 3,
    useGrouping: false
});

สิ่งนี้จะสร้างมูลค่าของ "005" สำหรับข้อความ คุณยังสามารถใช้ฟังก์ชัน toLocaleString ของ Number เพื่อ pad ค่าศูนย์ทางด้านขวาของจุดทศนิยม

var amount = 5;

var text = amount.toLocaleString('en-US',
{
    style: 'decimal',
    minimumFractionDigits: 2,
    useGrouping: false
});

สิ่งนี้จะสร้างมูลค่าของ "5.00" สำหรับข้อความ เปลี่ยนการใช้การจัดกลุ่มเป็นจริงเพื่อใช้ตัวคั่นจุลภาคเป็นหลัก

โปรดทราบว่าการใช้toLocaleString()with localesและoptionsอาร์กิวเมนต์เป็นมาตรฐานแยกต่างหากใน ECMA-402ไม่ใช่ใน ECMAScript ณ วันนี้เบราว์เซอร์บางตัวใช้การสนับสนุนขั้นพื้นฐานเท่านั้นเช่นtoLocaleString()อาจเพิกเฉยต่อข้อโต้แย้งใด ๆ

ตัวอย่างที่สมบูรณ์


ว้าวนี่เป็นวิธีที่สะอาดสุด ๆ และใช้งานได้ใน node.js
jishi

ฉันหัวเราะเบา ๆ เมื่อฉันอ่านคำนำ - "คำแนะนำที่ซับซ้อนไม่จำเป็น" การพัฒนาซอฟต์แวร์เช่นเดียวกับในทุกสาขาวิชาที่เกี่ยวข้องกับการชั่งน้ำหนักการแลกเปลี่ยน ฉันลองใช้ "วิธีมาตรฐาน" ด้วยตัวเอง - และตั้งเวลา ใช้งานได้จริง แต่ฉันจะไม่เลือกใช้กับแอปพลิเคชันซ้ำ ๆ ทุกชนิดเนื่องจากความช้าในการเปรียบเทียบกับโซลูชัน "โฮมรีด" อื่น ๆ อีกมากมาย
Bearvarine

1
จริง ๆ แล้วฟังก์ชั่น JavaScript ในตัวจำนวนมากทำงานได้ไม่ดีเมื่อวนลูปมากกว่าข้อมูลจำนวนมาก แต่ฉันจะเถียงว่าคุณไม่ควรใช้ JavaScript สำหรับสิ่งนั้นแม้กระทั่งฝั่งเซิร์ฟเวอร์เช่น Node.js หากคุณมีข้อมูลจำนวนมากในการประมวลผลฝั่งเซิร์ฟเวอร์คุณควรใช้แพลตฟอร์มที่ดีกว่าเช่น. NET หรือ Java หากคุณกำลังประมวลผลข้อมูลฝั่งไคลเอ็นต์เพื่อแสดงต่อผู้ใช้ปลายทางคุณควรประมวลผลข้อมูลสำหรับสิ่งที่คุณกำลังแสดงผลในขณะนี้ไปยังหน้าจอผู้ใช้ปลายทางเท่านั้น ตัวอย่างเช่นแสดงเฉพาะแถวที่มองเห็นได้ของตารางและไม่ประมวลผลข้อมูลสำหรับถนนอื่น
Daniel Barbalace

21

หากทราบหมายเลขการเติมล่วงหน้าไม่ให้เกินค่าที่กำหนดมีวิธีอื่นในการทำเช่นนี้โดยไม่มีลูป:

var fillZeroes = "00000000000000000000";  // max number of zero fill ever asked for in global

function zeroFill(number, width) {
    // make sure it's a string
    var input = number + "";  
    var prefix = "";
    if (input.charAt(0) === '-') {
        prefix = "-";
        input = input.slice(1);
        --width;
    }
    var fillAmt = Math.max(width - input.length, 0);
    return prefix + fillZeroes.slice(0, fillAmt) + input;
}

กรณีทดสอบที่นี่: http://jsfiddle.net/jfriend00/N87mZ/


@BrockAdams - แก้ไขทั้งสองกรณีที่คุณพูดถึง หากจำนวนนั้นกว้างเท่ากับความกว้างของการเติมจะไม่มีการเพิ่มการเติมใด ๆ
jfriend00

ขอบคุณ; +1 แม้ว่าตัวเลขติดลบจะออกเล็กน้อยจากการประชุมปกติ ในกรณีทดสอบของคุณ-88ควรให้ผล"-00088"เช่น
บร็อคอดัมส์

1
@BrockAdams - ฉันไม่แน่ใจว่าzeroFill(-88, 5)ควรโทร-00088หรือ-0088ไม่ ฉันเดาว่าขึ้นอยู่กับว่าคุณต้องการให้widthอาร์กิวเมนต์เป็นความกว้างทั้งหมดของตัวเลขหรือเพียงแค่จำนวนหลัก (ไม่รวมเครื่องหมายลบ) ผู้ใช้งานสามารถสลับการทำงานเพื่อไม่รวมเครื่องหมายลบได้อย่างง่ายดายเพียงแค่ลบ--widthบรรทัดของรหัส
jfriend00

19

วิธีที่รวดเร็วและสกปรก:

y = (new Array(count + 1 - x.toString().length)).join('0') + x;

สำหรับ x = 5 และนับ = 6 คุณจะได้ y = "000005"


1
ฉันได้รับy="0005"กับข้างต้นy = (new Array(count + 1 - x.toString().length)).join('0') + x;เป็นสิ่งที่ให้ฉันy="000005"
forforf

3
@OrrSiloni: การแก้ปัญหารหัสที่สั้นที่สุดคือจริง ๆ แล้ว('0000'+n).slice(-4)
Seaux

14

นี่คือฟังก์ชั่นด่วนที่ฉันคิดขึ้นมาเพื่อทำงาน หากใครมีวิธีที่ง่ายกว่าอย่าลังเลที่จะแบ่งปัน!

function zerofill(number, length) {
    // Setup
    var result = number.toString();
    var pad = length - result.length;

    while(pad > 0) {
        result = '0' + result;
        pad--;
    }

    return result;
}

ฉันไม่คิดว่าจะมีวิธี "เรียบง่าย" - มันจะเป็นหน้าที่ของบางอย่าง เราอาจมีการอภิปรายอัลกอริทึม แต่ในตอนท้ายของวันคุณจะยังคงจบลงด้วยฟังก์ชั่นที่เติมตัวเลข
Peter Bailey

คำแนะนำทั่วไปของฉันคือการใช้ลูป "สำหรับ" เนื่องจากโดยทั่วไปจะมีความเสถียรและรวดเร็วกว่าในภาษา ECMAScript (ActionScript 1-3 และ JavaScript)
cwallenpoole

หรือข้ามซ้ำทั้งหมด;)
ปีเตอร์เบลีย์

ฟังก์ชั่นที่เรียบง่าย? อาจจะไม่. อันที่ไม่วนซ้ำ? นั่นเป็นไปได้ ... แม้ว่าอัลกอริทึมนั้นไม่สำคัญทั้งหมด
coderjoe

1
ว้าวความคิดเห็นทั้งหมดข้างต้นค่อนข้างไม่ถูกต้อง โซลูชันของ @ profitehlolz นั้นเรียบง่ายและเหมาะสำหรับการทำอินไลน์ (ไม่จำเป็นต้องมีฟังก์ชั่น) ในขณะเดียวกันfor. vs whileประสิทธิภาพไม่แตกต่างกันพอที่จะน่าสนใจ: jsperf.com/fors-vs-while/34
broofa

12

ไปงานปาร์ตี้สายที่นี่ แต่ฉันมักจะใช้โครงสร้างนี้สำหรับการทำ ad-hoc padding ของค่าบางอย่างที่nรู้จักกันว่าเป็นทศนิยมบวก:

(offset + n + '').substr(1);

ที่ไหน offsetเลข 10 ^^

เช่น Padding ถึง 5 หลักโดยที่ n = 123:

(1e5 + 123 + '').substr(1); // => 00123

รุ่นฐานสิบหกของ verbose มากกว่านี้เล็กน้อย:

(0x100000 + 0x123).toString(16).substr(1); // => 00123

หมายเหตุ 1: ฉันชอบวิธีการแก้ปัญหาของ @ profitehlolz เช่นกันซึ่งเป็นเวอร์ชันสตริงของสิ่งนี้โดยใช้คุณลักษณะการลบดัชนีที่ดีของ slice ()


12

ฉันไม่รู้ว่าทำไมจริง ๆ แต่ไม่มีใครทำอย่างชัดเจนที่สุด นี่คือการดำเนินการของฉัน

ฟังก์ชั่น:

/** Pad a number with 0 on the left */
function zeroPad(number, digits) {
    var num = number+"";
    while(num.length < digits){
        num='0'+num;
    }
    return num;
}

ต้นแบบ:

Number.prototype.zeroPad=function(digits){
    var num=this+"";
    while(num.length < digits){
        num='0'+num;
    }
    return(num);
};

ตรงไปตรงมามากฉันไม่เห็นเลยว่ามันจะง่ายขนาดไหน ด้วยเหตุผลบางอย่างที่ฉันดูที่นี่หลายครั้งผู้คนก็พยายามที่จะหลีกเลี่ยง 'สำหรับ' และ 'ในขณะที่' วนรอบในทุก ๆ ค่าใช้จ่าย การใช้ regex อาจทำให้ต้นทุนเพิ่มมากขึ้นสำหรับการเว้นระยะห่าง 8 หลักเล็กน้อย


11

ฉันใช้ส่วนย่อยนี้เพื่อรับค่าตัวเลข 5 หลัก

(value+100000).toString().slice(-5) // "00123" with value=123


9

พลังของคณิตศาสตร์!

x = จำนวนเต็มถึง pad
y = จำนวนศูนย์ถึง pad

function zeroPad(x, y)
{
   y = Math.max(y-1,0);
   var n = (x / Math.pow(10,y)).toFixed(y);
   return n.replace('.','');  
}

9

ฉันไม่เห็นใครเลยชี้ให้เห็นความจริงที่ว่าเมื่อคุณใช้String.prototype.substr ()ด้วยจำนวนลบมันจะนับจากทางขวา

วิธีแก้ปัญหาหนึ่งซับสำหรับคำถามของ OP คือการแสดงเลขศูนย์ 6 หลักของเลข 5 คือ:

console.log(("00000000" + 5).substr(-6));

โดยทั่วไปเราจะได้รับ:

function pad(num, len) { return ("00000000" + num).substr(-len) };

console.log(pad(5, 6));
console.log(pad(45, 6));
console.log(pad(345, 6));
console.log(pad(2345, 6));
console.log(pad(12345, 6));


8

หลังจากใช้เวลานานนานในการทดสอบ 15 ฟังก์ชั่น / วิธีการที่แตกต่างกันซึ่งพบในคำถามนี้ฉันตอบได้ว่าตอนนี้ฉันรู้แล้วว่าตัวไหนดีที่สุด (หลากหลายที่สุดและเร็วที่สุด)

ฉันใช้เวลา 15 หน้าที่ / วิธีจากคำตอบสำหรับคำถามนี้และสร้างสคริปต์เพื่อวัดเวลาที่ใช้ในการประมวลผล 100 แผ่น แต่ละแผ่นจะรองหมายเลข9ด้วย2000ศูนย์ สิ่งนี้อาจดูมากเกินไป แต่มันก็เป็นความคิดที่ดีเกี่ยวกับการปรับขนาดของฟังก์ชั่น

รหัสที่ฉันใช้สามารถพบได้ที่นี่: https://gist.github.com/NextToNothing/6325915

อย่าลังเลที่จะแก้ไขและทดสอบโค้ดด้วยตัวเอง

เพื่อให้ได้วิธีที่หลากหลายที่สุดคุณต้องใช้การวนซ้ำ นี่เป็นเพราะมีจำนวนมากที่คนอื่น ๆ มีแนวโน้มที่จะล้มเหลวในขณะที่สิ่งนี้จะประสบความสำเร็จ

แล้ววงไหนที่จะใช้? นั่นจะเป็นการwhileวนซ้ำ forห่วงยังคงเป็นไปอย่างรวดเร็ว แต่whileวนซ้ำนั้นเร็วขึ้นเล็กน้อย (สองสามมิลลิวินาที) - และสะอาดกว่า

คำตอบเช่นเดียวกับที่โดยWilco, Aleksandar ToplekหรือVitim.usจะทำผลงานได้อย่างสมบูรณ์แบบ

โดยส่วนตัวแล้วฉันลองใช้วิธีอื่น ฉันพยายามใช้ฟังก์ชันเรียกซ้ำเพื่อวางสตริง / หมายเลข มันทำงานได้ดีกว่าวิธีการเข้าร่วมอาร์เรย์ แต่ยังไม่ได้ทำงานเร็วเท่าห่วง

ฟังก์ชั่นของฉันคือ

function pad(str, max, padder) {
  padder = typeof padder === "undefined" ? "0" : padder;
  return str.toString().length < max ? pad(padder.toString() + str, max, padder) : str;
}

คุณสามารถใช้ฟังก์ชั่นของฉันด้วยการตั้งค่าตัวแปร padding เช่นนี้

pad(1, 3); // Returns '001'
// - Or -
pad(1, 3, "x"); // Returns 'xx1'

โดยส่วนตัวหลังจากการทดสอบของฉันฉันจะใช้วิธีที่มีการวนรอบในขณะที่ชอบAleksandar ToplekหรือVitim.usหรืออย่างไรก็ตามฉันจะแก้ไขมันเล็กน้อยเพื่อให้คุณสามารถตั้งค่าสายแพ็ดดิง

ดังนั้นฉันจะใช้รหัสนี้:

function padLeft(str, len, pad) {
    pad = typeof pad === "undefined" ? "0" : pad + "";
    str = str + "";
    while(str.length < len) {
        str = pad + str;
    }
    return str;
}

// Usage
padLeft(1, 3); // Returns '001'
// - Or -
padLeft(1, 3, "x"); // Returns 'xx1'

คุณสามารถใช้มันเป็นฟังก์ชั่นต้นแบบโดยใช้รหัสนี้:

Number.prototype.padLeft = function(len, pad) {
    pad = typeof pad === "undefined" ? "0" : pad + "";
    var str = this + "";
    while(str.length < len) {
        str = pad + str;
    }
    return str;
}

// Usage
var num = 1;

num.padLeft(3); // Returns '001'
// - Or -
num.padLeft(3, "x"); // Returns 'xx1'

ฉันใส่สิ่งนี้ลงใน jsfiddle เพื่อให้ผู้อื่นทดสอบได้อย่างรวดเร็วโดยเพิ่มโค้ดของคุณ: jsfiddle.net/kevinmicke/vnvghw7y/2เวอร์ชันของคุณแข่งขันได้บ่อยและบางครั้งก็เร็วที่สุด ขอขอบคุณสำหรับการทดสอบอย่างละเอียดถี่ถ้วน
kevinmicke

8

พารามิเตอร์ที่หนึ่งคือจำนวนจริงใด ๆ พารามิเตอร์ที่สองคือจำนวนเต็มบวกที่ระบุจำนวนขั้นต่ำทางด้านซ้ายของจุดทศนิยมและพารามิเตอร์ที่สามเป็นจำนวนเต็มบวกตัวเลือกระบุหมายเลขถ้าตัวเลขทางด้านขวาของจุดทศนิยม

function zPad(n, l, r){
    return(a=String(n).match(/(^-?)(\d*)\.?(\d*)/))?a[1]+(Array(l).join(0)+a[2]).slice(-Math.max(l,a[2].length))+('undefined'!==typeof r?(0<r?'.':'')+(a[3]+Array(r+1).join(0)).slice(0,r):a[3]?'.'+a[3]:''):0
}

ดังนั้น

           zPad(6, 2) === '06'
          zPad(-6, 2) === '-06'
       zPad(600.2, 2) === '600.2'
        zPad(-600, 2) === '-600'
         zPad(6.2, 3) === '006.2'
        zPad(-6.2, 3) === '-006.2'
      zPad(6.2, 3, 0) === '006'
        zPad(6, 2, 3) === '06.000'
    zPad(600.2, 2, 3) === '600.200'
zPad(-600.1499, 2, 3) === '-600.149'


8

นี่คือโซลูชัน ES6

function pad(num, len) {
  return '0'.repeat(len - num.toString().length) + num;
}
alert(pad(1234,6));


ชัดเจนโซลูชันที่หรูหราที่สุดฉันจะแก้ไขเพื่อหลีกเลี่ยงการแปลง 2 สาย: const numStr = String(num)และreturn '0'.repeat(len - numStr.length) + numStr;
ngryman

8

ในเบราว์เซอร์สมัยใหม่ทั้งหมดที่คุณสามารถใช้ได้

numberStr.padStart(numberLength, "0");

function zeroFill(num, numLength) {
  var numberStr = num.toString();

  return numberStr.padStart(numLength, "0");
}

var numbers = [0, 1, 12, 123, 1234, 12345];

numbers.forEach(
  function(num) {
    var numString = num.toString();
    
    var paddedNum = zeroFill(numString, 5);

    console.log(paddedNum);
  }
);

นี่คือการอ้างอิง MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart


5

ไม่ใช่ว่าคำถามนี้ต้องการคำตอบเพิ่มเติม แต่ฉันคิดว่าฉันจะเพิ่มเวอร์ชัน Lodash แบบง่ายของนี้

_.padLeft(number, 6, '0')


1
ดีกว่า:var zfill = _.partialRight(_.padStart, '0');
Droogans

3
บางคนอาจจะประท้วง "ฉันไม่ต้องการใช้ lodash" แต่มันก็แทบจะเป็นข้อโต้แย้งที่ถูกต้องอีกต่อไปเนื่องจากคุณสามารถติดตั้งเฉพาะฟังก์ชั่นนี้: npm install --save lodash.padleftจากนั้นimport padLeft from 'lodash.padleft'และละเว้น_.
Andy

5

วิธีล่าสุดในการทำเช่นนี้ง่ายกว่ามาก:

var number = 2
number.toLocaleString(undefined, {minimumIntegerDigits:2})

output: "02"


(8).toLocaleString(undefined, {minimumIntegerDigits: 5})ส่งกลับ"00.008"สำหรับฉันตามตำแหน่งที่ตั้งของฉัน
le_m

5

เป็นอีกวิธีหนึ่ง แต่ฉันคิดว่ามันอ่านง่ายขึ้น

function zeroFill(text, size)
{
  while (text.length < size){
  	text = "0" + text;
  }
  
  return text;
}


เหมือนกับคนอื่น ๆ ?
ฟาบิโอพูดว่า Reinstate Monica

4

อันนี้มีถิ่นกำเนิดน้อยกว่า แต่อาจเร็วที่สุด ...

zeroPad = function (num, count) {
    var pad = (num + '').length - count;
    while(--pad > -1) {
        num = '0' + num;
    }
    return num;
};

pad = count - (num + '').lengthฉันคิดว่าคุณต้องการที่จะทำ จำนวนลบไม่ได้รับการจัดการที่ดี แต่นอกเหนือจากนั้นก็ไม่เลว +1
nickf

3

ทางออกของฉัน

Number.prototype.PadLeft = function (length, digit) {
    var str = '' + this;
    while (str.length < length) {
        str = (digit || '0') + str;
    }
    return str;
};

การใช้

var a = 567.25;
a.PadLeft(10); // 0000567.25

var b = 567.25;
b.PadLeft(20, '2'); // 22222222222222567.25

3

ทำไมไม่ใช้การเรียกซ้ำ

function padZero(s, n) {
    s = s.toString(); // in case someone passes a number
    return s.length >= n ? s : padZero('0' + s, n);
}

padZero (223, 3) ล้มเหลวด้วย '0223'
Serginho

ฉันคิดว่าฟังก์ชั่นนี้เรียกว่ามีสตริงเป็นพารามิเตอร์แรก อย่างไรก็ตามฉันแก้ไขมัน
lex82

2

การจับลิงบางตัวก็ใช้งานได้เช่นกัน

String.prototype.padLeft = function (n, c) {
  if (isNaN(n))
    return null;
  c = c || "0";
  return (new Array(n).join(c).substring(0, this.length-n)) + this; 
};
var paddedValue = "123".padLeft(6); // returns "000123"
var otherPadded = "TEXT".padLeft(8, " "); // returns "    TEXT"

1
-1 monkeypatching การตั้งชื่อระดับบนสุดใน javascript เป็นการปฏิบัติที่ไม่ดี
เจเรมีกำแพง

2
True สำหรับวัตถุและอาร์เรย์วัตถุ แต่ String ไม่เลว
โรดริโก

2
function pad(toPad, padChar, length){
    return (String(toPad).length < length)
        ? new Array(length - String(toPad).length + 1).join(padChar) + String(toPad)
        : toPad;
}

pad(5, 0, 6) = 000005

pad('10', 0, 2) = 10 // don't pad if not necessary

pad('S', 'O', 2) = SO

... ฯลฯ

ไชโย


ฉันคิดว่ามันควรจะเป็นมากกว่านี้: var s = String(toPad); return (s.length < length) ? new Array(length - s.length + 1).join('0') + s : s;หากคุณแก้ไขฉันจะลบการลงคะแนนของฉัน
drewish

@drewish ขอบคุณสำหรับการจับฉันเห็นด้วยกับการแก้ไขของคุณ (ยกเว้น hardcoded 0เข้าร่วมถ่าน :) - ตอบปรับปรุง
Madbreaks

ฉันคิดว่ามันจะดีกว่าถ้าเก็บสตริงไว้ในตัวแปรชั่วคราว ฉันทำการเปรียบเทียบบางอย่างกับที่นี่: jsperf.com/padding-with-memoizationนอกจากนี้ยังมีเกณฑ์มาตรฐานสำหรับการใช้งานใหม่ใน "อาร์เรย์ใหม่" ผลลัพธ์สำหรับใหม่นั้นมีอยู่ทั่วสถานที่ แต่ความทรงจำดูเหมือนจะเป็นไปได้
drewish

2

ง่าย , การแก้ปัญหามากที่สุดตรงไปข้างหน้าคุณจะได้พบกับ

function zerofill(number,length) {
    var output = number.toString();
    while(output.length < length) {
      output = '0' + output;
    }
    return output;
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.