Повторите символ 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 «а», поскольку он Array.joinпомещает аргумент между элементами массива.)

Саймон также указывает, что в соответствии с этим jsperf , кажется, что в Safari и Chrome (но не в Firefox) быстрее повторять символ несколько раз, просто добавляя цикл for (хотя и менее сжатый).

Джейсон Орендорфф
источник
4
Кроме того, вы можете использовать переменную вместо фиксированной длины - Array (20-len), скажем, для заполнения строки до 20.
John C
7
Метод цикла может быть быстрее, но он более многословен. Кроме того, я озадачен всеми ответами за первый комментарий, учитывая, что когда это обычно будет полезно, когда длина массива является переменной, напримерArray(rawValue.length + 1).join("*")
Dexygen
Это не работает в случаях 0 и 1, так как они дают одинаковые результаты.
Райан
2
Формула есть Array(n+1).join("a"). Когда n = 0, это возвращает пустую строку, а когда n = 1, это возвращает "a". Поэтому я думаю, что это работает во всех случаях.
Джейсон Орендорф
1
@Neel Это потому, что движки JS накладывают ограничение на длину строки. В Chrome и Firefox предел близок к 2 ^ 30 (около миллиарда). 10 ^ 12 - это один триллион.
Джейсон Орендорф
301

В новой гармонии ES6 у вас будет собственный способ сделать это с повторением . Также ES6 сейчас только экспериментальная, эта функция уже доступна в Edge, FF, Chrome и Safari

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

И конечно, если функция повтора недоступна, вы можете использовать old-good 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)  )

Kennebec
источник
53
Плохая практика кодирования загрязняет встроенные прототипы.
Туомассало
3
@nurettin, см. programmers.stackexchange.com/questions/104320/… для дальнейшего обсуждения. Я бы добавил (правильно распределенную) статическую вспомогательную функцию с подписью repeat(str, n).
Туомассало
4
Я бы удалил n= n || 1часть (или проверил, если nона не определена), так что вы также можете повторить 0время.
chodorowicz
3
Также взгляните на официальный полифилл Mozilla для ES6: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Эйрик Биркеланд,
3
@ChrisV, String.repeatбыл добавлен только в ES6, который не был завершен до июня 2015 года. Так что я думаю, что моя точка зрения была действительной, когда я написал ее в 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;? что это за заявление?
Цахи Ашер
Значит, это полифилл для нативного повтора, тогда? Просто добавьте if (!String.prototype.repeat) {начало и }конец.
trlkly
>>> = является беззнаковым назначением правого сдвига (как в count = count >>> 1), см .: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
user1441004
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

Если вы не против включения библиотеки в ваш проект, у lodash есть функция повтора.

_.repeat('*', 3);
// → '***

https://lodash.com/docs#repeat

Натан Дейнджер
источник
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, вы также можете использовать метод repeat.
Мишель
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"
);
yckart
источник
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()) 
    };
webdeb
источник
SCRIPT5029: длина массива должна быть конечным положительным целым числом при попытке использовать этот подход
andrepaulo
5

Другой интересный способ быстро повторить n символов - использовать идею из алгоритма быстрого возведения в степень:

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;
};
csharpfolk
источник
Почему вы говорите «интересный путь»? что тут интересного? Это очевидное решение, самый основной фундаментальный пример компьютерной программы.
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,'🌹'); // => "🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹"
Alejandro
источник
1

Вот что я использую:

function repeat(str, num) {
        var holder = [];
        for(var i=0; i<num; i++) {
            holder.push(str);
        }
        return holder.join('');
    }
Кушик дас
источник
0

Я собираюсь расширить ответ @ Bonbon . Его метод - это простой способ «добавить N символов в существующую строку», на всякий случай, если кому-то понадобится это сделать. Например, «гугл» - это 1, за которым следуют 100 нулей .

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 (), которая доступна не во всех браузерах. Он называется _.repeat и доступен начиная с версии 3.0.0:

_.repeat('a', 10);
0x4a6f4672
источник
0
var stringRepeat = function(string, val) {
  var newString = [];
    for(var i = 0; i < val; i++) {
      newString.push(string);
  }
  return newString.join('');
}

var repeatedString = stringRepeat("a", 1);
гадость
источник
0

Может использоваться как однострочник:

function repeat(str, len) {
    while (str.length < len) str += str.substr(0, len-str.length);
    return str;
}
сарсапарель
источник
На любом конкурсе «за» проходит быстрее, чем «пока». :-)
Junihh
0

В CoffeeScript:

( 'a' for dot in [0..10]).join('')
Дэвид Мендес
источник
0

Вот как вы можете вызвать функцию и получить результат с помощью Array () и join ().

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"
Caglayan ALTINCI
источник
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))

Maxali
источник