Par exemple, si j'avais "scissors"
dans variable et que je voulais connaître la position de toutes les occurrences de la lettre "s"
, il devrait imprimer 1, 4, 5, 8
Comment puis-je faire cela en JavaScript de la manière la plus efficace? Je ne pense pas que boucler à travers le tout est terriblement efficace
Une simple boucle fonctionne bien:
var str = "scissors";
var indices = [];
for(var i=0; i<str.length;i++) {
if (str[i] === "s") indices.Push(i);
}
Maintenant, vous indiquez que vous voulez 1,4,5,8. Cela vous donnera 0, 3, 4, 7 puisque les index sont basés sur zéro. Vous pouvez donc en ajouter un:
if (str[i] === "s") indices.Push(i+1);
et maintenant cela vous donnera le résultat attendu.
Un violon peut être vu ici .
Je ne pense pas que boucler à travers le tout est terriblement efficace
En ce qui concerne les performances, je ne pense pas que ce soit un sujet de préoccupation grave jusqu'à ce que vous commenciez à avoir des problèmes.
Voici un jsPerf test comparant différentes réponses. Dans Safari 5.1, IndexOf est le meilleur. Dans Chrome 19, la boucle for est la plus rapide.
Utilisation de la méthode native String.prototype.indexOf
pour rechercher le plus efficacement possible chaque décalage.
function locations(substring,string){
var a=[],i=-1;
while((i=string.indexOf(substring,i+1)) >= 0) a.Push(i);
return a;
}
console.log(locations("s","scissors"));
//-> [0, 3, 4, 7]
C'est une micro-optimisation, cependant. Pour une boucle simple et laconique qui sera assez rapide:
// Produces the indices in reverse order; throw on a .reverse() if you want
for (var a=[],i=str.length;i--;) if (str[i]=="s") a.Push(i);
En fait, une boucle native est plus rapide sur chrome que sur indexOf
!
Lorsque j’ai tout évalué, il me semblait que les expressions régulières donnaient les meilleurs résultats, alors j’ai eu cette idée.
function indexesOf(string, regex) {
var match,
indexes = {};
regex = new RegExp(regex);
while (match = regex.exec(string)) {
if (!indexes[match[0]]) indexes[match[0]] = [];
indexes[match[0]].Push(match.index);
}
return indexes;
}
tu peux le faire
indexesOf('ssssss', /s/g);
qui reviendrait
{s: [0,1,2,3,4,5]}
j'avais besoin d'un moyen très rapide de faire correspondre plusieurs caractères à de grandes quantités de texte. Par exemple, vous pouvez le faire.
indexesOf('dddddssssss', /s|d/g);
et vous obtiendriez ceci
{d:[0,1,2,3,4], s:[5,6,7,8,9,10]}
de cette façon, vous pouvez obtenir tous les index de vos matchs en une seule fois.
function charPos(str, char) {
return str
.split("")
.map(function (c, i) { if (c == char) return i; })
.filter(function (v) { return v >= 0; });
}
charPos("scissors", "s"); // [0, 3, 4, 7]
Notez que JavaScript compte à partir de 0. Ajoutez +1 à i
, si vous devez.
Plus amusant, mais aussi plus général: Ceci trouve les index de départ d'une sous-chaîne de any length dans une chaîne
const length = (x) => x.length
const sum = (a, b) => a+b
const indexesOf = (substr) => ({
in: (str) => (
str
.split(substr)
.slice(0, -1)
.map(length)
.map((_, i, lengths) => (
lengths
.slice(0, i+1)
.reduce(sum, i*substr.length)
))
)
});
console.log(indexesOf('s').in('scissors')); // [0,3,4,7]
console.log(indexesOf('and').in('a and b and c')); // [2,8]
indices = (c, s) => s
.split('')
.reduce((a, e, i) => e === c ? a.concat(i) : a, []);
indices('?', 'a?g??'); // [1, 3, 4]
Vous pourriez aussi probablement utiliser la fonction match () de javascript. Vous pouvez créer une expression régulière puis la transmettre en tant que paramètre à match ().
stringName.match(/s/g);
Cela devrait vous retourner un tableau de toutes les occurrences de la lettre.
J'ai adoré la question et j'ai pensé écrire ma réponse en utilisant la méthode reduce()
définie sur les tableaux.
function getIndices(text, delimiter='.') {
let indices = [];
let combined;
text.split(delimiter)
.slice(0, -1)
.reduce((a, b) => {
if(a == '') {
combined = a + b;
} else {
combined = a + delimiter + b;
}
indices.Push(combined.length);
return combined; // Uncommenting this will lead to syntactical errors
}, '');
return indices;
}
let indices = getIndices(`Ab+Cd+Pk+Djb+Nice+One`, '+');
let indices2 = getIndices(`Program.can.be.done.in.2.ways`); // Here default delimiter will be taken as `.`
console.log(indices); // [ 2, 5, 8, 12, 17 ]
console.log(indices2); // [ 7, 11, 14, 19, 22, 24 ]
// To get output as expected (comma separated)
console.log(`${indices}`); // 2,5,8,12,17
console.log(`${indices2}`); // 7,11,14,19,22,24