ทำซ้ำตัวละคร N ครั้ง


602

ใน Perl ฉันสามารถทำซ้ำตัวละครหลายครั้งโดยใช้ไวยากรณ์:

$a = "a" x 10; // results in "aaaaaaaaaa"

มีวิธีง่ายๆในการทำสิ่งนี้ใน Javascript หรือไม่? เห็นได้ชัดว่าฉันสามารถใช้ฟังก์ชั่นได้ แต่ฉันสงสัยว่ามีวิธีการในตัวหรือเทคนิคที่ชาญฉลาดอื่น ๆ

คำตอบ:


1201

วันนี้, repeatวิธีสตริงจะดำเนินการเกือบทุกที่ ( ไม่ได้อยู่ใน Internet Explorer ) ดังนั้นหากคุณไม่ต้องการสนับสนุนเบราว์เซอร์รุ่นเก่าคุณสามารถเขียน:

"a".repeat(10)

ก่อนหน้าrepeatนี้เราใช้แฮ็คนี้:

Array(11).join("a") // create string with 10 a's: "aaaaaaaaaa"

(โปรดทราบว่าอาร์เรย์ที่มีความยาว 11 ทำให้คุณได้รับเพียง 10 "a" เนื่องจากArray.joinใส่อาร์กิวเมนต์ระหว่างองค์ประกอบอาร์เรย์)

Simon ยังชี้ให้เห็นว่าตามjsperf นี้ดูเหมือนว่าเร็วกว่าใน Safari และ Chrome (แต่ไม่ใช่ Firefox) เพื่อทำซ้ำตัวละครหลาย ๆ ครั้งโดยการต่อท้ายโดยใช้ for for loop (แม้ว่าจะสั้นกว่าเล็กน้อย)


4
นอกจากนี้คุณสามารถใช้ตัวแปรแทนความยาวคงที่ - Array (20-len) บอกให้แปะสตริงมากถึง 20
John C

7
วิธีการวนอาจเร็วขึ้น แต่ verbose มากขึ้น นอกจากนี้ฉันยังงงงวย upvotes ทั้งหมดสำหรับความคิดเห็นแรกพิจารณาว่าเมื่อนี้โดยทั่วไปจะเป็นประโยชน์เมื่อความยาว Array แปรผันเช่นArray(rawValue.length + 1).join("*")
Dexygen

กรณีนี้ใช้ไม่ได้กับกรณี 0 และ 1 เนื่องจากจะให้ผลลัพธ์ที่เหมือนกัน
Ryan

2
Array(n+1).join("a")สูตรคือ เมื่อ n = 0 ผลตอบแทนนี้สตริงที่ว่างเปล่าและเมื่อ n = 1 "a"ก็จะส่งกลับ ดังนั้นฉันคิดว่ามันใช้ได้ในทุกกรณี
Jason Orendorff

1
@Neel นั่นเป็นเพราะเครื่องยนต์ JS กำหนดขีดจำกัดความยาวของสตริง ใน Chrome และ Firefox ขีด จำกัด อยู่ใกล้กับ 2 ^ 30 (ประมาณหนึ่งพันล้าน) 10 ^ 12 คือหนึ่งล้านล้าน
Jason Orendorff

301

ในความสามัคคี ES6 ใหม่คุณจะมีวิธีพื้นเมืองสำหรับการทำเช่นนี้ด้วยซ้ำ นอกจากนี้ ES6 ในขณะนี้เป็นการทดลองเท่านั้นคุณลักษณะนี้มีให้ใน Edge, FF, Chrome และ Safari แล้ว

"abc".repeat(3) // "abcabcabc"

และแน่นอนว่าถ้าฟังก์ชั่นเล่นซ้ำไม่สามารถใช้งานได้คุณสามารถใช้ฟังก์ชั่นเก่า ๆ ได้ดี Array(n + 1).join("abc")


54

สะดวกถ้าคุณทำซ้ำตัวเองมาก:

String.prototype.repeat = String.prototype.repeat || function(n){
  n= n || 1;
  return Array(n+1).join(this);
}

alert(  'Are we there yet?\nNo.\n'.repeat(10)  )


53
มันเป็นวิธีการเข้ารหัสที่ไม่ดีในการสร้างต้นแบบของมลภาวะในตัว
tuomassalo

3
@nurettin ดูprogrammers.stackexchange.com/questions/104320/…สำหรับการสนทนาเพิ่มเติม ฉันต้องการเพิ่ม (กำหนดขอบเขตอย่างถูกต้อง) repeat(str, n)ฟังก์ชั่นผู้ช่วยคงที่มีลายเซ็นของ
tuomassalo

4
ฉันจะลบn= n || 1ส่วน (หรือตรวจสอบnว่าไม่ได้กำหนด) ดังนั้นคุณสามารถทำซ้ำ0ครั้ง
chodorowicz

3
นอกจากนี้ยังมีการดูโพลีฟิลอย่างเป็นทางการของ Mozilla สำหรับ ES6: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/
......

3
@ChrisV String.repeatถูกเพิ่มเข้ามาใน ES6 เท่านั้นซึ่งยังไม่ได้ข้อสรุปจนถึงเดือนมิถุนายน 2558 ดังนั้นฉันคิดว่าประเด็นของฉันถูกต้องเมื่อฉันเขียนมันในปี 2012 :)
tuomassalo

13

วิธีที่มีประสิทธิภาพมากที่สุดคือhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat

รุ่นสั้นอยู่ด้านล่าง

  String.prototype.repeat = function(count) {
    if (count < 1) return '';
    var result = '', pattern = this.valueOf();
    while (count > 1) {
      if (count & 1) result += pattern;
      count >>>= 1, pattern += pattern;
    }
    return result + pattern;
  };
  var a = "a";
  console.debug(a.repeat(10));

Polyfill จาก Mozilla:

if (!String.prototype.repeat) {
  String.prototype.repeat = function(count) {
    'use strict';
    if (this == null) {
      throw new TypeError('can\'t convert ' + this + ' to object');
    }
    var str = '' + this;
    count = +count;
    if (count != count) {
      count = 0;
    }
    if (count < 0) {
      throw new RangeError('repeat count must be non-negative');
    }
    if (count == Infinity) {
      throw new RangeError('repeat count must be less than infinity');
    }
    count = Math.floor(count);
    if (str.length == 0 || count == 0) {
      return '';
    }
    // Ensuring count is a 31-bit integer allows us to heavily optimize the
    // main part. But anyway, most current (August 2014) browsers can't handle
    // strings 1 << 28 chars or longer, so:
    if (str.length * count >= 1 << 28) {
      throw new RangeError('repeat count must not overflow maximum string size');
    }
    var rpt = '';
    for (;;) {
      if ((count & 1) == 1) {
        rpt += str;
      }
      count >>>= 1;
      if (count == 0) {
        break;
      }
      str += str;
    }
    // Could we try:
    // return Array(count + 1).join(this);
    return rpt;
  }
}

นี่เป็นสิ่งที่ดี แต่ "การทำซ้ำ" แบบใหม่ของเจ้าของภาษานั้นเร็วกว่าและไม่จำเป็นต้องมีการดำเนินการเลยขอบคุณ!
Goty Metal

1
คุณสามารถอธิบายความหมายของcount >>>= 1, pattern += pattern;? มันเป็นคำพูดแบบไหน?
Tsahi Asher

ดังนั้นนี่คือ polyfill สำหรับการทำซ้ำแบบดั้งเดิมใช่ไหม เพียงเพิ่มif (!String.prototype.repeat) {จุดเริ่มต้นและ}จุดสิ้นสุด
trlkly

>>> = คือการมอบหมายการเลื่อนขวาที่ไม่ได้ลงชื่อ (เช่นนับ = นับ >>> 1) ดู: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/
......

12

ทางเลือกคือ:

for(var word = ''; word.length < 10; word += 'a'){}

หากคุณต้องการทำซ้ำหลายตัวอักษรคูณเงื่อนไขของคุณ:

for(var word = ''; word.length < 10 * 3; word += 'foo'){}

หมายเหตุ:คุณไม่จำเป็นต้องมีขนาดเกิน 1 ด้วยเช่นกันword = Array(11).join('a')



10

สำหรับเบราว์เซอร์ทั้งหมด

ฟังก์ชั่นต่อไปนี้จะทำงานเร็วกว่าตัวเลือกที่แนะนำในคำตอบที่ยอมรับ:

var repeat = function(str, count) {
    var array = [];
    for(var i = 0; i < count;)
        array[i++] = str;
    return array.join('');
}

คุณจะใช้มันแบบนี้:

var repeatedString = repeat("a", 10);

เพื่อเปรียบเทียบประสิทธิภาพของฟังก์ชั่นนี้กับของตัวเลือกที่เสนอในคำตอบที่ยอมรับดูซอนี้และซอนี้สำหรับการวัดประสิทธิภาพ

สำหรับเบราว์เซอร์ที่ทันสมัยเท่านั้น

ในเบราว์เซอร์สมัยใหม่คุณสามารถทำได้โดยใช้String.prototype.repeatวิธีการ:

var repeatedString = "a".repeat(10);

อ่านเพิ่มเติมเกี่ยวกับวิธีการนี้ในMDN

ตัวเลือกนี้เร็วยิ่งขึ้น น่าเสียดายที่มันไม่ทำงานใน Internet Explorer เวอร์ชันใด ๆ ตัวเลขในตารางระบุเวอร์ชันเบราว์เซอร์แรกที่รองรับวิธีการอย่างสมบูรณ์:

ป้อนคำอธิบายรูปภาพที่นี่


9
Array(10).fill('a').join('')

แม้ว่าคำตอบที่ได้รับการโหวตมากที่สุดนั้นจะมีขนาดเล็กกว่าเล็กน้อย แต่ด้วยวิธีนี้คุณไม่จำเป็นต้องเพิ่มรายการอาเรย์พิเศษ


1
น่าเสียดายที่วิธีการเติมไม่ได้รับการสนับสนุนใน IE และหากคุณไม่รองรับ IE คุณสามารถใช้วิธีการทำซ้ำได้เช่นกัน
Michiel

1
ทำไมคุณถึงต้องใช้วิธีการพิเศษfill()หากคุณทำแบบนี้ด้วยตัวjoin("a")เอง ...
vsync

7
/**  
 * Repeat a string `n`-times (recursive)
 * @param {String} s - The string you want to repeat.
 * @param {Number} n - The times to repeat the string.
 * @param {String} d - A delimiter between each string.
 */

var repeat = function (s, n, d) {
    return --n ? s + (d || "") + repeat(s, n, d) : "" + s;
};

var foo = "foo";
console.log(
    "%s\n%s\n%s\n%s",

    repeat(foo),        // "foo"
    repeat(foo, 2),     // "foofoo"
    repeat(foo, "2"),   // "foofoo"
    repeat(foo, 2, "-") // "foo-foo"
);

7

ใน ES2015 / ES6 คุณสามารถใช้ "*".repeat(n)

ดังนั้นเพียงแค่เพิ่มสิ่งนี้เข้ากับโครงการของคุณและคุณก็พร้อม

  String.prototype.repeat = String.prototype.repeat || 
    function(n) {
      if (n < 0) throw new RangeError("invalid count value");
      if (n == 0) return "";
      return new Array(n + 1).join(this.toString()) 
    };

SCRIPT5029: ความยาวอาร์เรย์ต้องเป็นจำนวนเต็มบวกแน่นอนเมื่อลองใช้วิธีนี้
andrepaulo

5

อีกวิธีที่น่าสนใจในการทำซ้ำอักขระอย่างรวดเร็วคือการใช้แนวคิดจากอัลกอริทึมการยกกำลังอย่างรวดเร็ว:

var repeatString = function(string, n) {
    var result = '', i;

    for (i = 1; i <= n; i *= 2) {
        if ((n & i) === i) {
            result += string;
        }
        string = string + string;
    }

    return result;
};

ทำไมคุณถึงพูดว่า "วิธีที่น่าสนใจ" ที่นี่น่าสนใจจัง มันเป็นทางออกที่ชัดเจนซึ่งเป็นตัวอย่างพื้นฐานที่สุดของโปรแกรมคอมพิวเตอร์
vsync

2

สำหรับการทำซ้ำค่าในโครงการของฉันฉันใช้การทำซ้ำ

ตัวอย่างเช่น:

var n = 6;
for (i = 0; i < n; i++) {
    console.log("#".repeat(i+1))
}

แต่ต้องระวังเนื่องจากวิธีนี้ได้ถูกเพิ่มเข้ากับข้อมูลจำเพาะ ECMAScript 6


2
function repeatString(n, string) {
  var repeat = [];
  repeat.length = n + 1;
  return repeat.join(string);
}

repeatString(3,'x'); // => xxx
repeatString(10,'🌹'); // => "🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹"

1

นี่คือสิ่งที่ฉันใช้:

function repeat(str, num) {
        var holder = [];
        for(var i=0; i<num; i++) {
            holder.push(str);
        }
        return holder.join('');
    }

0

ฉันจะขยายตัวใน@ คำตอบของ วิธีการของเขาเป็นวิธีที่ง่ายในการ "ผนวก N chars ไปยังสตริงที่มีอยู่" ในกรณีที่ทุกคนต้องการทำเช่นนั้น ยกตัวอย่างเช่นตั้งแต่ว่า "Google" เป็น 1 ตามด้วยศูนย์

for(var google = '1'; google.length < 1 + 100; google += '0'){}
document.getElementById('el').innerText = google;
<div>This is "a google":</div>
<div id="el"></div>

หมายเหตุ:คุณจะต้องเพิ่มความยาวของสตริงเดิมลงในเงื่อนไข


0

Lodashนำเสนอฟังก์ชั่นที่คล้ายกันกับฟังก์ชั่นJavascript ซ้ำ ()ซึ่งไม่สามารถใช้ได้กับเบราว์เซอร์ทั้งหมด มันถูกเรียกว่า_.repeatและมีให้ตั้งแต่รุ่น 3.0.0:

_.repeat('a', 10);


0

สามารถใช้เป็นหนึ่งซับได้เช่นกัน:

function repeat(str, len) {
    while (str.length < len) str += str.substr(0, len-str.length);
    return str;
}

ในการแข่งขันใด ๆ "สำหรับ" เร็วกว่า "ขณะ" :-)
Junihh


0

นี่คือวิธีที่คุณสามารถเรียกใช้ฟังก์ชันและรับผลลัพธ์โดยใช้ Array () และเข้าร่วม ()

function repeatStringNumTimes(str, num) {
  // repeat after me
  return num > 0 ? Array(num+1).join(str) : "";
}

console.log(repeatStringNumTimes("a",10))


-1
String.prototype.repeat = function (n) { n = Math.abs(n) || 1; return Array(n + 1).join(this || ''); };

// console.log("0".repeat(3) , "0".repeat(-3))
// return: "000" "000"

1
การเขียนทับนี้จะString.prototype.repeatถูกรวมไว้ในเบราว์เซอร์ปัจจุบัน นอกจากนี้ทำไมจึงย่อขนาดให้เล็กลง? คุณไม่จำเป็นต้องเขียนมันทั้งหมดในบรรทัดเดียว
เครื่องปั่น

ไม่มีฟีเจอร์ 'ทำซ้ำ' ใน IE ดังนั้นจึงจำเป็นต้องมีต้นแบบ
Caglayan ALTINCI

-3

นี่คือรุ่น ES6

const repeat = (a,n) => Array(n).join(a+"|$|").split("|$|");
repeat("A",20).forEach((a,b) => console.log(a,b+1))

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.