it-swarm.com.de

Alle Indizes eines angegebenen Zeichens in einer Zeichenfolge suchen

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

43
Ageis

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.

enter image description here

69
vcsjones

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!

 Graph of performance results from the link

20
Phrogz

 benchmark

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

8
Chad Scira
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.

7
Tomalak

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]

5
davnicwil
indices = (c, s) => s
          .split('')
          .reduce((a, e, i) => e === c ? a.concat(i) : a, []);

indices('?', 'a?g??'); // [1, 3, 4]
1
tpdi

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.

1
Yash Kalwani

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
0
hygull