Повторить строку - Javascript

Каков наилучший или наиболее краткий способ возврата строки, повторяющейся произвольное количество раз?

Вот мой лучший снимок на данный момент:

function repeat(s, n){
    var a = [];
    while(a.length < n){
        a.push(s);
    }
    return a.join('');
}

Более 10 лет назад у меня было хорошо известное решение этой проблемы, которое я использовал в качестве примера в статье по оптимизации JavaScript за пару месяцев до того, как вы задали этот вопрос: webreference.com/programming/javascript/jkm3/3.html Очевидно, большинство людей забыли об этом коде, и я не вижу ниже столь же хороших решений, как мое. Лучший алгоритм выглядит так, как будто он был взят из моего кода; за исключением неправильного понимания того, как работает мой код, он выполняет один дополнительный шаг экспоненциальной конкатенации, который исключается в моем оригинале с помощью специального цикла.

Joseph Myers 23.07.2013 06:36

Попробуйте это сравнение и подумайте об изменении принятого ответа на существующее давнее решение этой проблемы, опубликованное до того, как этот вопрос когда-либо был задан. jsperf.com/repeating-strings

Joseph Myers 24.07.2013 03:08

Никто не поднял решение Джозефа. Алгоритм 3700 лет. Стоимость дополнительной ступеньки ничтожна. А эта статья содержит ошибки и заблуждения относительно конкатенации строк в Javascript. Для всех, кто интересуется тем, как Javascript действительно обрабатывает строки внутри, см. Веревка.

wnrph 16.09.2013 18:09

Кажется, никто не заметил, что повторение прототипа String определено и реализовано, по крайней мере, в firefox.

kennebec 03.06.2014 00:26

@kennebec: Да, это функция EcmaScript 6, которой не было, когда задавали этот вопрос. Сейчас он довольно хорошо поддерживается.

rvighne 20.06.2014 01:19

@rvighne - я только что проверил kangax.github.io/compat-table/es6/#String.prototype.repeat, я бы не стал считать поддержку исключительно из firefox и chrome "достаточно хорошо поддерживаемой"

aaaaaa 11.03.2015 08:04

Как говорится в комментарии Кеннебека и в ответе Андре Ласло для ES6: 'mystring'.repeat(xTimes)

Benj 22.06.2016 15:42

@brad Не могли бы вы изменить принятый ответ на Вот этот, пожалуйста?

Bergi 21.12.2020 01:42

Конечно! Поменял только сейчас.

brad 22.12.2020 03:16
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
274
9
146 194
29
Перейти к ответу Данный вопрос помечен как решенный

Ответы 29

function repeat(s, n) { var r = ""; for (var a=0;a<n;a++) r+=s; return r;}

Разве конкатенация строк не требует больших затрат? По крайней мере, так обстоит дело с Java.

Vijay Dev 17.08.2009 21:29

Почему да, они есть. Однако его нельзя оптимизировать в javascript. :(

McTrafik 16.03.2011 21:17

Как насчет этого повышения производительности: var r=s; for (var a=1;... :)))) В любом случае, согласно этому тесту (jsperf.com/string-repeat/2) выполнение простого цикла for с объединением строк, как то, что вы предложили, кажется намного быстрее в Chrome по сравнению с использованием Array.join.

Marco Demaio 26.03.2011 17:39

@VijayDev - не по этому тесту: jsperf.com/ultimate-concat-vs-join

jbyrd 04.10.2011 18:44

Note to new readers: This answer is old and and not terribly practical - it's just "clever" because it uses Array stuff to get String things done. When I wrote "less process" I definitely meant "less code" because, as others have noted in subsequent answers, it performs like a pig. So don't use it if speed matters to you.

Я бы поместил эту функцию непосредственно в объект String. Вместо того, чтобы создавать массив, заполнять его и присоединять к нему пустым символом, просто создайте массив надлежащей длины и соедините его с желаемой строкой. Тот же результат, меньше процесса!

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

alert( "string to repeat\n".repeat( 4 ) );

Я стараюсь не расширять нативные объекты, но в остальном это прекрасное решение. Спасибо!

brad 15.10.2008 00:22

Это очень умно. Я не могу дождаться возможности воспользоваться им.

Joel Anair 15.10.2008 00:33

@ brad - а почему бы и нет? Вы бы предпочли загрязнить глобальное пространство имен функцией, у которой есть довольно четко определенный дом (объект String)?

Peter Bailey 15.10.2008 01:18

BaileyP: Расширение встроенных объектов ломает вещи. В случае строки это не так уж плохо, но для массива и т. д. Вы создаете проблемы

Orion Edwards 15.10.2008 05:26

Что, если кто-то еще захочет определить String.repeat для чего-то другого? Может быть, это в библиотеке, которую вы используете, или, может быть, в другом программисте в вашей команде. Бывает.

Joel Coehoorn 15.10.2008 06:38

Фактически, оба ваших аргумента применимы и к глобальному пространству имен. Если я собираюсь расширить пространство имен и иметь потенциальные коллизии, я бы предпочел сделать это 1) не в глобальном, 2) в релевантном и 3) легко реорганизовать. Это означает размещение его в прототипе String, а не в global.

Peter Bailey 17.10.2008 02:49

одно изменение, которое я внесу в эту функцию, заключалось бы в том, чтобы поместить parseInt () вокруг «num», поскольку, если у вас есть числовая строка, вы можете получить странное поведение из-за манипулирования типами JS. например: "моя строка" .repeat ("6") == "61"

nickf 19.05.2009 06:28

Если вы не хотите расширять собственные объекты, вы можете вместо этого поместить функцию в объект String, например: String.repeat = function(string, num){ return new Array(parseInt(num) + 1).join(string); };. Назовите это так: String.repeat('/\', 20)

Znarkus 31.08.2010 18:51

@nickf: Люди не должны передавать строки функциям, ожидающим числа.

ThiefMaster 08.05.2011 16:36

Если вы собираетесь использовать parseInt, используйте систему счисления (parseInt(num, 10)); в противном случае вы получите неприятный сюрприз, если в num в начале будет 0 (он будет проанализирован как восьмеричный). В идеале просто используйте + num (new Array(+num + 1)).

Andreas Grech 02.03.2012 10:56

Версия CoffeeScript: String::repeat = (n) -> new Array(n + 1).join @

Felix Rabe 07.04.2013 18:46

Или num | 0, если мы говорим о синтаксическом разборе int из строк и споре типов javascript. Однако, поскольку несколько других функций в типе js проверяют аргументы, я действительно не вижу в этом смысла. Не отправляйте строку в функцию, которая требует числа.

kb. 20.01.2014 05:54

Это действительно плохо

Lourenzo Ferreira 11.06.2014 04:37

Просто случайный Вау. @LourenzoFerreira: Что ты имеешь в виду? Пожалуйста, будьте конструктивны, спасибо.

loveNoHate 06.02.2015 01:01

Я попытался упростить эту функцию, и в результате получилось: return [](+num).join(this);

Jesús Otero 30.03.2015 05:01

@ JesúsOtero Мне это не кажется "упрощенным", просто короче. Намного труднее понять, что делает код.

Sven Slootweg 17.05.2015 10:11

Просто ПРИМЕЧАНИЕ: Array.join () в несколько раз медленнее, чем даже подходы грубой силы, указанные ниже: Disfated, безусловно, имеет самый надежный ответ как с точки зрения скорости, так и с точки зрения потребления памяти и неиспользования рекурсии. (поскольку высота стека может стать невообразимо большой), а array.join создает копии при копиях подстрок, а также при вызовах внутренних функций.

Decoded 12.02.2016 23:06

Красиво, иногда простота и удобочитаемость важнее производительности.

Alex 08.03.2016 14:07

/**  
@desc: repeat string  
@param: n - times  
@param: d - delimiter  
*/

String.prototype.repeat = function (n, d) {
    return --n ? this + (d || '') + this.repeat(n, d) : '' + this
};

вот как повторить строку несколько раз, используя разделитель.

Расширение Решение П. Бейли:

String.prototype.repeat = function(num) {
    return new Array(isNaN(num)? 1 : ++num).join(this);
    }

Таким образом вы будете защищены от неожиданных типов аргументов:

var foo = 'bar';
alert(foo.repeat(3));              // Will work, "barbarbar"
alert(foo.repeat('3'));            // Same as above
alert(foo.repeat(true));           // Same as foo.repeat(1)

alert(foo.repeat(0));              // This and all the following return an empty
alert(foo.repeat(false));          // string while not causing an exception
alert(foo.repeat(null));
alert(foo.repeat(undefined));
alert(foo.repeat({}));             // Object
alert(foo.repeat(function () {})); // Function

Обновлено: Благодарим Джерон за его элегантную идею ++num!

Немного изменил ваш: String.prototype.repeat = function(n){return new Array(isNaN(n) ? 1 : ++n).join(this);}

jerone 13.07.2010 21:44

В любом случае, согласно этому тесту (jsperf.com/string-repeat/2) выполнение простого цикла for с объединением строк кажется намного быстрее в Chrome по сравнению с использованием Array.join. Разве это не смешно ?!

Marco Demaio 26.03.2011 17:43

Это довольно эффективно

String.prototype.repeat = function(times){
    var result = "";
    var pattern=this;
    while (times > 0) {
        if (times&1)
            result+=pattern;
        times>>=1;
        pattern+=pattern;
    }
    return result;
};

@Olegs, я думаю, что идея голосования меньше, чем голосование за человека или за творчество человека (что действительно приветствуется), но идея состоит в том, чтобы проголосовать за наиболее полное решение, чтобы его можно было легко найти на вверху списка, без необходимости читать все ответы в поисках идеального. (Потому что, к сожалению, у всех нас мало времени ...)

Sorin Postelnicu 25.05.2013 03:18

Я протестировал работоспособность всех предложенных подходов.

Вот самый быстрый вариант у меня есть.

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;
};

Или как функция автономный:

function repeat(pattern, count) {
    if (count < 1) return '';
    var result = '';
    while (count > 1) {
        if (count & 1) result += pattern;
        count >>= 1, pattern += pattern;
    }
    return result + pattern;
}

Он основан на алгоритме Artistoex. Это действительно быстро. И чем больше count, тем быстрее он движется по сравнению с традиционным подходом new Array(count + 1).join(string).

Я изменил только 2 вещи:

  1. заменил pattern = this на pattern = this.valueOf() (устраняет одно очевидное преобразование типа);
  2. добавлена ​​проверка if (count < 1) из prototypejs в начало функции, чтобы исключить ненужные действия в этом случае.
  3. применена оптимизация от Деннисотвечать (5-7% ускорения)

UPD

Для желающих создана небольшая площадка для тестирования производительности здесь.

переменная count ~ 0 .. 100:

Performance diagram

константа count = 1024:

Performance diagram

Используйте это и сделайте это еще быстрее, если сможете :)

Хорошо сделано! Считаю, что корпус count < 1 действительно лишняя оптимизация.

Jeroen Versteeg 27.03.2013 16:19

Отличный алгоритм O (log N). Спасибо за отличную оптимизацию с помощью valueOf ()

vp_arth 22.12.2013 23:41

Ссылки на изображения мертвы.

Benjamin Gruenbaum 24.05.2014 18:20

Ссылки в порядке. Может быть временная недоступность

disfated 25.05.2014 08:57

Тестовый JSFiddle больше не работает правильно; кажется, он просто запускает первую функцию снова и снова (оставил ее работать на полчаса, чтобы быть уверенным)

RevanProdigalKnight 21.05.2015 17:17

Это может быть самый маленький рекурсивный: -

String.prototype.repeat = function(n,s) {
s = s || ""
if (n>0) {
   s += this
   s = this.repeat(--n,s)
}
return s}

Рекурсивное решение с использованием разделяй и властвуй:

function repeat(n, s) {
    if (n==0) return '';
    if (n==1 || isNaN(n)) return s;
    with(Math) { return repeat(floor(n/2), s)+repeat(ceil(n/2), s); }
}

Испытания различных методов:

var repeatMethods = {
    control: function (n,s) {
        /* all of these lines are common to all methods */
        if (n==0) return '';
        if (n==1 || isNaN(n)) return s;
        return '';
    },
    divideAndConquer:   function (n, s) {
        if (n==0) return '';
        if (n==1 || isNaN(n)) return s;
        with(Math) { return arguments.callee(floor(n/2), s)+arguments.callee(ceil(n/2), s); }
    },
    linearRecurse: function (n,s) {
        if (n==0) return '';
        if (n==1 || isNaN(n)) return s;
        return s+arguments.callee(--n, s);
    },
    newArray: function (n, s) {
        if (n==0) return '';
        if (n==1 || isNaN(n)) return s;
        return (new Array(isNaN(n) ? 1 : ++n)).join(s);
    },
    fillAndJoin: function (n, s) {
        if (n==0) return '';
        if (n==1 || isNaN(n)) return s;
        var ret = [];
        for (var i=0; i<n; i++)
            ret.push(s);
        return ret.join('');
    },
    concat: function (n,s) {
        if (n==0) return '';
        if (n==1 || isNaN(n)) return s;
        var ret = '';
        for (var i=0; i<n; i++)
            ret+=s;
        return ret;
    },
    artistoex: function (n,s) {
        var result = '';
        while (n>0) {
            if (n&1) result+=s;
            n>>=1, s+=s;
        };
        return result;
    }
};
function testNum(len, dev) {
    with(Math) { return round(len+1+dev*(random()-0.5)); }
}
function testString(len, dev) {
    return (new Array(testNum(len, dev))).join(' ');
}
var testTime = 1000,
    tests = {
        biggie: { str: { len: 25, dev: 12 }, rep: {len: 200, dev: 50 } },
        smalls: { str: { len: 5, dev: 5}, rep: { len: 5, dev: 5 } }
    };
var testCount = 0;
var winnar = null;
var inflight = 0;
for (var methodName in repeatMethods) {
    var method = repeatMethods[methodName];
    for (var testName in tests) {
        testCount++;
        var test = tests[testName];
        var testId = methodName+':'+testName;
        var result = {
            id: testId,
            testParams: test
        }
        result.count=0;

        (function (result) {
            inflight++;
            setTimeout(function () {
                result.start = +new Date();
                while ((new Date() - result.start) < testTime) {
                    method(testNum(test.rep.len, test.rep.dev), testString(test.str.len, test.str.dev));
                    result.count++;
                }
                result.end = +new Date();
                result.rate = 1000*result.count/(result.end-result.start)
                console.info(result);
                if (winnar === null || winnar.rate < result.rate) winnar = result;
                inflight--;
                if (inflight==0) {
                    console.info('The winner: ');
                    console.info(winnar);
                }
            }, (100+testTime)*testCount);
        }(result));
    }
}

Вот безопасная версия JSLint

String.prototype.repeat = function (num) {
  var a = [];
  a.length = num << 0 + 1;
  return a.join(this);
};

Вот 5-7% улучшение по сравнению с ответом disfated.

Разверните цикл, остановившись на count > 1, и выполните дополнительное объединение result += pattnern после цикла. Это позволит избежать зацикливания завершающего ранее неиспользованного pattern += pattern без необходимости использовать дорогостоящую if-check. Окончательный результат будет выглядеть так:

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;
    }
    result += pattern;
    return result;
};

И вот раздвоенная рабочий пример, разветвленная для развернутой версии: http://jsfiddle.net/wsdfg/

Если вы думаете, что все эти определения прототипов, создание массивов и операции соединения излишни, просто используйте однострочный код там, где он вам нужен. Строка S повторяется N раз:

for (var i = 0, result = ''; i < N; i++) result += S;

Код должен быть читабельным. Если вы буквально каждый раз собираетесь использовать его только один раз, отформатируйте его должным образом (или используйте метод Array(N + 1).join(str), если это не является узким местом для производительности). Если есть малейшая вероятность, что вы собираетесь использовать его дважды, переместите его в функцию с соответствующим именем.

cloudfeet 13.06.2013 16:35

Я пришел сюда случайно, и раньше у меня не было причин повторять char в javascript.

На меня произвело впечатление то, как artistoex это сделала, и разочаровал результаты. Я заметил, что последняя строка concat не нужна, как также указал Деннис.

Я заметил еще несколько вещей, играя с дискредитированным сэмплом вместе взятым.

Результаты сильно различались, часто в пользу последнего прогона, и аналогичные алгоритмы часто пытались занять позицию. Одна из вещей, которые я изменил, заключалась в том, что вместо использования сгенерированного JSLitmus счетчика в качестве начального числа для вызовов; поскольку счетчик генерировался по-разному для разных методов, я добавил индекс. Это сделало вещь намного более надежной. Затем я посмотрел на то, чтобы в функции передавались строки разного размера. Это предотвратило некоторые из вариаций, которые я видел, когда некоторые алгоритмы лучше работали с одиночными символами или меньшими строками. Однако все 3 лучших метода хорошо себя зарекомендовали, независимо от размера строки.

Раздвоенный тестовый набор

http://jsfiddle.net/schmide/fCqp3/134/

// repeated string
var string = '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789';
// count paremeter is changed on every test iteration, limit it's maximum value here
var maxCount = 200;

var n = 0;
$.each(tests, function (name) {
    var fn = tests[name];
    JSLitmus.test(++n + '. ' + name, function (count) {
        var index = 0;
        while (count--) {
            fn.call(string.slice(0, index % string.length), index % maxCount);
            index++;
        }
    });
    if (fn.call('>', 10).length !== 10) $('body').prepend('<h1>Error in "' + name + '"</h1>');
});

JSLitmus.runAll();

Затем я включил исправление Денниса и решил посмотреть, смогу ли я найти способ получить немного больше.

Поскольку javascript не может реально оптимизировать вещи, лучший способ повысить производительность - избегать чего-либо вручную. Если бы я взял первые 4 тривиальных результата из цикла, я мог бы избежать 2-4 строковых хранилищ и записать окончательное хранилище непосредственно в результат.

// final: growing pattern + prototypejs check (count < 1)
'final avoid': function (count) {
    if (!count) return '';
    if (count == 1) return this.valueOf();
    var pattern = this.valueOf();
    if (count == 2) return pattern + pattern;
    if (count == 3) return pattern + pattern + pattern;
    var result;
    if (count & 1) result = pattern;
    else result = '';
    count >>= 1;
    do {
        pattern += pattern;
        if (count & 1) result += pattern;
        count >>= 1;
    } while (count > 1);
    return result + pattern + pattern;
}

Это привело к улучшению в среднем на 1-2% по сравнению с исправлением Денниса. Тем не менее, разные прогоны и разные браузеры будут показывать достаточно справедливую дисперсию, так что этот дополнительный код, вероятно, не стоит усилий по сравнению с двумя предыдущими алгоритмами.

Диаграмма

Обновлено: я делал это в основном под хромом. Firefox и IE часто на пару процентов отдают предпочтение Деннису.

Простой способ:

String.prototype.repeat = function(num) {
    num = parseInt(num);
    if (num < 0) return '';
    return new Array(num + 1).join(this);
}

Рабочий пример: http://jsfiddle.net/3Y9v2/

function repeat(s, n){
    return ((new Array(n+1)).join(s));
}
alert(repeat('R', 10));

Люди чрезмерно усложняют это до смехотворной степени или тратят зря производительность. Массивы? Рекурсия? Ты меня разыгрываешь.

function repeat (string, times) {
  var result = ''
  while (times-- > 0) result += string
  return result
}

Редактировать. Я провел несколько простых тестов для сравнения с побитовой версией, опубликованной artistoex / disfated и другими людьми. Последний был лишь ненамного быстрее, но на несколько порядков эффективнее с памятью. Для 1000000 повторений слова «бла» процесс Node увеличился до 46 мегабайт с помощью простого алгоритма конкатенации (см. Выше), но только 5,5 мегабайт с помощью логарифмического алгоритма. Последнее, безусловно, лучший вариант. Репост для ясности:

function repeat (string, times) {
  var result = ''
  while (times > 0) {
    if (times & 1) result += string
    times >>= 1
    string += string
  }
  return result
}

В половине случаев у вас есть резервный string += string.

nikolay 23.03.2016 11:36

Простая рекурсивная конкатенация

Я просто хотел дать ему удар, и сделал это:

function ditto( s, r, c ) {
    return c-- ? ditto( s, r += s, c ) : r;
}

ditto( "foo", "", 128 );

Не могу сказать, что я много думал об этом, и это, наверное, видно :-)

Этот возможно лучше

String.prototype.ditto = function( c ) {
    return --c ? this + this.ditto( c ) : this;
};

"foo".ditto( 128 );

И это очень похоже на уже опубликованный ответ - я знаю это.

Но зачем вообще быть рекурсивным?

А как насчет небольшого поведения по умолчанию?

String.prototype.ditto = function() {
    var c = Number( arguments[ 0 ] ) || 2,
        r = this.valueOf();
    while ( --c ) {
        r += this;
    }
    return r;
}

"foo".ditto();

Потому что, хотя нерекурсивный метод будет обрабатывать произвольно большие повторы без выхода за пределы стека вызовов, он намного медленнее.

Почему я потрудился добавить больше методов, которые не наполовину меньше умный, чем уже опубликованные?

Отчасти для собственного развлечения, а отчасти для того, чтобы указать самым простым способом, я знаю, что есть много способов снять шкуру с кошки, и в зависимости от ситуации вполне возможно, что метод Лучший, очевидно, не идеален.

Относительно быстрый и сложный метод может привести к сбою и сгоранию при определенных обстоятельствах, в то время как более медленный и простой метод может со временем выполнить свою работу.

Некоторые методы могут быть не более чем эксплойтами и, как таковые, склонны к тому, что фиксированный не существует, а другие методы могут прекрасно работать в любых условиях, но построены так, что один просто не знает, как это работает.

«Так что, если я не знаю, как это работает ?!»

Серьезно?

JavaScript страдает одной из самых сильных сторон; он очень терпим к плохому поведению и настолько гибок, что может изгибаться назад, чтобы вернуть результаты, хотя для всех было бы лучше, если бы он щелкнул!

"С большой властью приходит большая ответственность" ;-)

Но что более серьезно и важно, хотя общие вопросы, подобные этому, действительно приводят к удивительным результатам в форме умный, он отвечает, что, как минимум, расширяет знания и кругозор, в конце концов, поставленную задачу - практический сценарий, который использует полученный метод - может потребоваться немного меньше или немного больше умный, чем предлагается.

Эти алгоритмы "идеально" забавны и все такое, но "один размер подходит всем" редко, если вообще когда-либо, будет лучше, чем сделанный на заказ.

Эта проповедь была доставлена ​​вам из-за недостатка сна и преходящего интереса. Идите и пишите код!

Ответ принят как подходящий

Хорошие новости! String.prototype.repeat - это теперь часть JavaScript.

"yo".repeat(2);
// returns: "yoyo"

Этот метод поддерживается всеми основными браузерами, кроме Internet Explorer. Актуальный список см. В MDN: String.prototype.repeat> Совместимость с браузером.

В MDN есть полифилл для браузеров без поддержки.

Спасибо за отчет о текущем состоянии дел, хотя я думаю, что полифилл Mozilla слишком сложен для большинства нужд (я предполагаю, что они пытаются имитировать поведение своей эффективной реализации C), поэтому на самом деле они не отвечают требованию OP относительно краткости. Любой из других подходов, созданных как полифил, обязательно будет более лаконичным ;-)

Guss 18.12.2014 16:22

Определенно! Но при использовании встроенного варианта обязательно должен быть самый лаконичный. Поскольку полифилы в основном представляют собой просто обратные порты, они могут быть немного сложными для обеспечения совместимости со спецификациями (или предлагаемыми спецификациями в данном случае). Я добавил его для полноты, полагаю, ОП решает, какой метод использовать.

André Laszlo 18.12.2014 16:57

Во-первых, вопросы OP, похоже, касаются краткости - что, как я понимаю, означает «простой и легкий для чтения», в то время как большинство ответов, похоже, касаются эффективности - что, очевидно, не одно и то же, и я также думаю, что если вы не реализуете какие-то очень конкретные алгоритмы обработки больших данных, не должны беспокоить вас, когда вы приступаете к реализации основных функций Javascript для манипулирования данными. Лаконичность гораздо важнее.

Во-вторых, как заметил Андре Ласло, String.repeat является частью ECMAScript 6 и уже доступен в нескольких популярных реализациях, поэтому самая краткая реализация String.repeat - это не реализовывать его ;-)

Наконец, если вам нужно поддерживать хосты, которые не предлагают реализацию ECMAScript 6, полифилл MDN, упомянутый Андре Ласло, совсем не лаконичен.

Итак, без лишних слов - вот мой полифилл лаконичный:

String.prototype.repeat = String.prototype.repeat || function(n){
    return n<=1 ? this : this.concat(this.repeat(n-1));
}

Да, это рекурсия. Мне нравятся рекурсии - они простые и, если все сделано правильно, их легко понять. Что касается эффективности, если язык поддерживает ее, они могут быть очень эффективными, если написаны правильно.

Судя по моим тестам, этот метод примерно на 60% быстрее, чем подход Array.join. Хотя это, очевидно, нигде не идет вразрез с обезличенной реализацией, она намного проще, чем обе.

Моя тестовая установка - это узел v0.10, использующий «Строгий режим» (я думаю, что он включает своего рода ТШО), вызывающий repeat(1000) для 10-символьной строки миллион раз.

String.prototype.repeat теперь является стандартом ES6.

'abc'.repeat(3); //abcabcabc

красивый! .. но мне не подходит (не поддерживается на ios <9): kangax.github.io/compat-table/es6

Benjamin 10.10.2015 13:10

@Benjamin Воспользуйтесь полифилом по ссылке.

Lewis 11.10.2015 07:54

Думаю, должен быть ответ приколот.

test30 02.03.2016 13:18

Используйте Array(N+1).join("string_to_repeat")

Мне это нравится. Идк, почему его там нет.

Joe Thomas 02.12.2015 01:49

любить это. так просто и чисто

ekkis 19.12.2015 06:12

Используйте Lodash для служебных функций Javascript, таких как повторяющиеся строки.

Lodash обеспечивает хорошую производительность и совместимость с ECMAScript.

Я настоятельно рекомендую его для разработки пользовательского интерфейса, и он также хорошо работает на стороне сервера.

Вот как повторить строку «yo» 2 раза с помощью Lodash:

> _.repeat('yo', 2)
"yoyo"

Для всех браузеров

Это примерно так же кратко, как и получается:

function repeat(s, n) { return new Array(n+1).join(s); }

Если вы также заботитесь о производительности, это гораздо лучший подход:

function repeat(s, n) { var a=[],i=0;for(;i<n;)a[i++]=s;return a.join(''); }

Если вы хотите сравнить производительность обоих вариантов, см. Тестовые тесты эта рабочий пример и эта рабочий пример. Во время моих собственных тестов второй вариант был примерно в 2 раза быстрее в Firefox и примерно в 4 раза быстрее в Chrome!

Только для современных браузеров:

В современных браузерах теперь также можно сделать это:

function repeat(s,n) { return s.repeat(n) };

Этот вариант не только короче, чем оба других варианта, но и даже быстрее, чем второй вариант.

К сожалению, это не работает ни в одной версии Internet Explorer. Числа в таблице указывают первую версию браузера, полностью поддерживающую метод:

function repeat(pattern, count) {
  for (var result = '';;) {
    if (count & 1) {
      result += pattern;
    }
    if (count >>= 1) {
      pattern += pattern;
    } else {
      return result;
    }
  }
}

Вы можете проверить это на JSFiddle. По сравнению с взломанным Array.join, мой, грубо говоря, От 10 (Chrome) до 100 (Safari) до 200 (Firefox) раз быстрее (в зависимости от браузера).

Объединение строк на основе числа.

function concatStr(str, num) {
   var arr = [];

   //Construct an array
   for (var i = 0; i < num; i++)
      arr[i] = str;

   //Join all elements
   str = arr.join('');

   return str;
}

console.info(concatStr("abc", 3));

Надеюсь, это поможет!

В ES-Next есть много способов

1. ES2015 / ES6 был реализован этот метод repeat()!

/** 
 * str: String
 * count: Number
 */
const str = `hello repeat!\n`, count = 3;

let resultString = str.repeat(count);

console.info(`resultString = \n${resultString}`);
/*
resultString = 
hello repeat!
hello repeat!
hello repeat!
*/

({ toString: () => 'abc', repeat: String.prototype.repeat }).repeat(2);
// 'abcabc' (repeat() is a generic method)

// Examples

'abc'.repeat(0);    // ''
'abc'.repeat(1);    // 'abc'
'abc'.repeat(2);    // 'abcabc'
'abc'.repeat(3.5);  // 'abcabcabc' (count will be converted to integer)
// 'abc'.repeat(1/0);  // RangeError
// 'abc'.repeat(-1);   // RangeError

2. ES2017 / ES8, новое добавление String.prototype.padStart()

const str = 'abc ';
const times = 3;

const newStr = str.padStart(str.length * times, str.toUpperCase());

console.info(`newStr =`, newStr);
// "newStr  = " "ABC ABC abc "

3. ES2017 / ES8, новое добавление String.prototype.padEnd()

const str = 'abc ';
const times = 3;

const newStr = str.padEnd(str.length * times, str.toUpperCase());

console.info(`newStr =`, newStr);
// "newStr  = " "abc ABC ABC "

реф.

http://www.ecma-international.org/ecma-262/6.0/#sec-string.prototype.repeat

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd

Еще одна функция повтора:

function repeat(s, n) {
  var str = '';
  for (var i = 0; i < n; i++) {
    str += s;
  }
  return str;
}

С ES8 вы также можете использовать для этого padStart или padEnd. например.

var str = 'cat';
var num = 23;
var size = str.length * num;
"".padStart(size, str) // outputs: 'catcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcat'

Чтобы повторить строку заданное количество раз, мы можем использовать встроенный метод repeat() в JavaScript.

Вот пример, в котором следующая строка повторяется 4 раза:

const name = "king";

const repeat = name.repeat(4);

console.info(repeat);

Выход:

"kingkingkingking"

или мы можем создать нашу собственную версию функции repeat() следующим образом:

function repeat(str, n) {
  if (!str || !n) {
    return;
  }

 let final = "";
  while (n) {
    final += s;
    n--;
  }
  return final;
}

console.info(repeat("king", 3))

(изначально размещено на https://reactgo.com/javascript-repeat-string/)

Другие вопросы по теме