275 votes

Chaîne de répétition - Javascript

Quelle est la méthode la plus efficace ou la plus concise pour renvoyer une chaîne de caractères répétée un nombre arbitraire de fois ?

Ce qui suit est mon meilleur essai jusqu'à présent :

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

5 votes

Il y a plus de 10 ans, j'ai trouvé une solution bien connue à ce problème, que j'ai utilisée comme exemple dans un article sur l'optimisation du JavaScript quelques mois avant que vous ne posiez cette question : webreference.com/programmation/javascript/jkm3/3.html Apparemment, la plupart des gens ont oublié ce code, et je ne vois pas de solution aussi bonne que la mienne. Le meilleur algorithme semble avoir été repris de mon code ; sauf qu'en raison d'une mauvaise compréhension du fonctionnement de mon code, il effectue une étape supplémentaire de concaténation exponentielle qui est éliminée dans mon code original par une boucle spéciale.

0 votes

Veuillez essayer cette comparaison et envisager de remplacer la réponse acceptée par la solution de longue date à ce problème, publiée avant même que cette question ne soit posée. jsperf.com/repeating-strings

11 votes

Personne n'a levé la solution de Joseph. L'algorithme a 3700 ans. Le coût de cette étape supplémentaire est négligeable. En outre, le coût de l'étape supplémentaire est négligeable. cet article contient des erreurs et des idées fausses concernant la concaténation de chaînes de caractères en Javascript. Pour toute personne intéressée par la manière dont Javascript gère réellement les chaînes de caractères en interne, voir Corde .

3voto

Fordi Points 917

Tests des différentes méthodes :

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.log(result);
                if (winnar === null || winnar.rate < result.rate) winnar = result;
                inflight--;
                if (inflight==0) {
                    console.log('The winner: ');
                    console.log(winnar);
                }
            }, (100+testTime)*testCount);
        }(result));
    }
}

3voto

Erik Aigner Points 7182

Voici la version sécurisée par JSLint

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

3voto

John Slegers Points 509

Pour tous les navigateurs

C'est à peu près ce qu'il y a de plus concis :

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

Si vous vous souciez également de la performance, cette approche est bien meilleure :

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

Si vous souhaitez comparer les performances des deux options, reportez-vous à la rubrique ce violon y ce violon pour les tests de référence. Lors de mes propres tests, la deuxième option était environ 2 fois plus rapide dans Firefox et environ 4 fois plus rapide dans Chrome !

Pour les navigateurs modernes uniquement :

Dans les navigateurs modernes, vous pouvez également le faire :

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

Cette option est non seulement plus courte que les deux autres, mais elle est aussi plus facile à mettre en œuvre. encore plus rapide que la deuxième option.

Malheureusement, il ne fonctionne dans aucune version d'Internet explorer. Les chiffres du tableau indiquent la première version du navigateur qui prend en charge la méthode :

enter image description here

3voto

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

Vous pouvez le tester à l'adresse suivante JSFiddle . Comparé à l'outil hacky Array.join et le mien l'est, grosso modo, 10 (Chrome) à 100 (Safari) à 200 (Firefox) fois plus rapide (en fonction du navigateur).

3voto

xgqfrms Points 2718

Il existe de nombreux moyens dans l ES-Next voies

1. ES2015 / ES6 a été réalisée cette repeat() méthode !

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

let resultString = str.repeat(count);

console.log(`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 nouvel ajout String.prototype.padStart()

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

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

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

3. ES2017 / ES8 nouvel ajout String.prototype.padEnd()

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

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

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

refs

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X