Wenn ich zum Beispiel "scissors"
in Variable hatte und die Position aller Vorkommen des Buchstabens "s"
wissen wollte, sollte 1, 4, 5, 8
ausgegeben werden.
Wie kann ich dies in JavaScript möglichst effizient tun? Ich finde nicht, dass das Durchlaufen des Ganzen äußerst effizient ist
Eine einfache Schleife funktioniert gut:
var str = "scissors";
var indices = [];
for(var i=0; i<str.length;i++) {
if (str[i] === "s") indices.Push(i);
}
Jetzt geben Sie an, dass Sie 1,4,5,8 wollen. Dadurch erhalten Sie 0, 3, 4, 7, da die Indizes auf Null basieren. Sie könnten also eins hinzufügen:
if (str[i] === "s") indices.Push(i+1);
und jetzt erhalten Sie Ihr erwartetes Ergebnis.
Eine Geige kann hier sehen.
Ich finde nicht, dass das Durchlaufen des Ganzen äußerst effizient ist
Was die Performance angeht, glaube ich nicht, dass Sie sich Sorgen machen müssen, bis Sie Probleme bekommen.
Hier ist ein jsPerf Test, der verschiedene Antworten vergleicht. In Safari 5.1 erzielt der IndexOf die besten Ergebnisse. In Chrome 19 ist die for-Schleife die schnellste.
Verwenden Sie die native String.prototype.indexOf
-Methode, um jeden Offset am effizientesten zu finden.
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]
Dies ist jedoch eine Mikrooptimierung. Für eine einfache und knappe Schleife, die schnell genug ist:
// 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);
Tatsächlich ist eine native Schleife schneller als die Verwendung von indexOf
!
Als ich alles untersuchte, schien es mir, als würden reguläre Ausdrücke die besten Ergebnisse erzielen. Daher kam ich dazu
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;
}
du kannst das
indexesOf('ssssss', /s/g);
was würde wiederkommen
{s: [0,1,2,3,4,5]}
ich brauchte eine sehr schnelle Methode, um mehrere Zeichen mit großen Textmengen abzugleichen. So könnten Sie dies zum Beispiel tun
indexesOf('dddddssssss', /s|d/g);
und du würdest das bekommen
{d:[0,1,2,3,4], s:[5,6,7,8,9,10]}
auf diese Weise können Sie alle Indexe Ihrer Spiele auf einmal abrufen
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]
Beachten Sie, dass JavaScript von 0 zählt. Fügen Sie +1 zu i
hinzu, wenn Sie müssen.
Mehr Funktionsspaß und auch allgemeiner: Dies findet die Anfangsindizes eines Teilstrings von any length in einem String
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]
Sie könnten wahrscheinlich auch die match () - Funktion von Javascript verwenden. Sie können einen regulären Ausdruck erstellen und ihn dann als Parameter an match () übergeben.
stringName.match(/s/g);
Dies sollte ein Array aller Vorkommen der Buchstaben 's' zurückgeben.
Ich war begeistert von der Frage und dachte daran, meine Antwort mit der reduce()
-Methode zu schreiben, die für Arrays definiert ist.
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