131

大文字と小文字を区別せずに、別の文字列で文字列がすべて出現する位置を見つけようとしています。

たとえば、次の文字列があるとします。

レバノンでウクレレを習いました。

と検索文字列le、配列を取得したい:

[2, 25, 27, 33]

どちらの文字列も変数になります。つまり、値をハードコードすることはできません。

これは正規表現では簡単な作業だと思いましたが、機能するものを見つけるのにしばらく苦労した後、うまくいきませんでした。

を使用してこれを達成する方法のこの例を見つけまし.indexOf()たが、確かにそれを行うにはもっと簡潔な方法が必要ですか?

4

18 に答える 18

189
var str = "I learned to play the Ukulele in Lebanon."
var regex = /le/gi, result, indices = [];
while ( (result = regex.exec(str)) ) {
    indices.push(result.index);
}

アップデート

元の質問で、検索文字列を変数にする必要があることを見つけられませんでした。を使用してこのケースに対処する別のバージョンを作成したindexOfので、最初の場所に戻ります。コメントでWrikkenが指摘したように、正規表現を使用して一般的なケースでこれを行うには、特殊な正規表現文字をエスケープする必要があります。その時点で、正規表現ソリューションは価値があるというよりも頭痛の種になると思います.

function getIndicesOf(searchStr, str, caseSensitive) {
    var searchStrLen = searchStr.length;
    if (searchStrLen == 0) {
        return [];
    }
    var startIndex = 0, index, indices = [];
    if (!caseSensitive) {
        str = str.toLowerCase();
        searchStr = searchStr.toLowerCase();
    }
    while ((index = str.indexOf(searchStr, startIndex)) > -1) {
        indices.push(index);
        startIndex = index + searchStrLen;
    }
    return indices;
}

var indices = getIndicesOf("le", "I learned to play the Ukulele in Lebanon.");

document.getElementById("output").innerHTML = indices + "";
<div id="output"></div>

于 2010-08-04T23:05:09.307 に答える
21

正規表現のないバージョンは次のとおりです。

function indexes(source, find) {
  if (!source) {
    return [];
  }
  // if find is empty string return all indexes.
  if (!find) {
    // or shorter arrow function:
    // return source.split('').map((_,i) => i);
    return source.split('').map(function(_, i) { return i; });
  }
  var result = [];
  for (i = 0; i < source.length; ++i) {
    // If you want to search case insensitive use 
    // if (source.substring(i, i + find.length).toLowerCase() == find) {
    if (source.substring(i, i + find.length) == find) {
      result.push(i);
    }
  }
  return result;
}

indexes("I learned to play the Ukulele in Lebanon.", "le")

EDIT : 'aaaa' や 'aa' などの文字列を照合して [0, 2] を検索する場合は、次のバージョンを使用します。

function indexes(source, find) {
  if (!source) {
    return [];
  }
  if (!find) {
      return source.split('').map(function(_, i) { return i; });
  }
  var result = [];
  var i = 0;
  while(i < source.length) {
    if (source.substring(i, i + find.length) == find) {
      result.push(i);
      i += find.length;
    } else {
      i++;
    }
  }
  return result;
}
于 2010-08-04T23:03:02.760 に答える
20

あなたは確かにこれを行うことができます!

//make a regular expression out of your needle
var needle = 'le'
var re = new RegExp(needle,'gi');
var haystack = 'I learned to play the Ukulele';

var results = new Array();//this is the results you want
while (re.exec(haystack)){
  results.push(re.lastIndex);
}

編集:RegExpのスペルを学ぶ

また、これはまさにあなたが望むものではないことに気付きました.針の始まりではなく終わりを教えてくれますが、それは近いです-結果配列にlastIndexプッシュすることができます...re.lastIndex-needle.length

編集:リンクを追加

@Tim Down の回答は RegExp.exec() の結果オブジェクトを使用しており、私のすべての Javascript リソースはその使用法を隠しています (一致する文字列を提供することは別として)。したがって、彼が を使用する場合result.index、それはある種の名前のない一致オブジェクトです。execのMDC 記述では、実際にこのオブジェクトを詳細に記述しています。

于 2010-08-04T23:03:54.347 に答える
2
const findAllOccurrences = (str, substr) => {
  str = str.toLowerCase();
  
  let result = [];

  let idx = str.indexOf(substr)
  
  while (idx !== -1) {
    result.push(idx);
    idx = str.indexOf(substr, idx+1);
  }
  return result;
}

console.log(findAllOccurrences('I learned to play the Ukulele in Lebanon', 'le'));
于 2021-07-29T15:42:26.450 に答える
1

ティムの答えをお勧めします。ただし、@blazs によるこのコメントsearchStr=aaaには、「と仮定するとstr=aaaaaa、ループ内で searchStr.length によってスキップを行っているため、コードは 4 つのオカレンスを見つけるのではなく、2 つだけを見つけることになります。」と述べられています。具体的には次の行ですstartIndex = index + searchStrLen;。Tim のコードは、それ自体の長さの範囲内にある検索対象の文字列のインスタンスを見つけることができません。だから、私はティムの答えを修正しました:

function getIndicesOf(searchStr, str, caseSensitive) {
    var startIndex = 0, index, indices = [];
    if (!caseSensitive) {
        str = str.toLowerCase();
        searchStr = searchStr.toLowerCase();
    }
    while ((index = str.indexOf(searchStr, startIndex)) > -1) {
        indices.push(index);
        startIndex = index + 1;
    }
    return indices;
}
var searchStr = prompt("Enter a string.");
var str = prompt("What do you want to search for in the string?");
var indices = getIndicesOf(str, searchStr);

document.getElementById("output").innerHTML = indices + "";
<div id="output"></div>

+ 1の代わりにに変更すると、 strと searchStr が の+ searchStrLen場合、インデックス 1 をインデックス配列に入れることができます。aaaaaaaaa

PS コードがどのように機能するかを説明するためにコード内のコメントが必要な場合は、そのように言ってください。喜んで対応させていただきます。

于 2020-09-14T15:31:46.703 に答える
0

これは、位置に応じて文字列インデックスを取得するために通常使用するものです。

次のパラメータを渡します。

search : 検索する文字列

find : 検索する文字列

position (デフォルトでは「all」): 検索文字列が検索文字列に表示される位置

('all' の場合、インデックスの完全な配列を返します)

('last' の場合、最後の位置を返します)

function stringIndex (search, find, position = "all") {
    
    var currIndex = 0, indexes = [], found = true;
    
    while (found) {        
        var searchIndex = search.indexOf(find);
        if (searchIndex > -1) {
            currIndex += searchIndex + find.length; 
            search = search.substr (searchIndex + find.length);
            indexes.push (currIndex - find.length);
        } else found = false; //no other string to search for - exit from while loop   
    }
    
    if (position == 'all') return indexes;
    if (position > indexes.length -1) return [];
    
    position = (position == "last") ? indexes.length -1 : position;
    
    return indexes[position];        
}

//Example:
    
var myString = "Joe meets Joe and together they go to Joe's house";
console.log ( stringIndex(myString, "Joe") ); //0, 10, 38
console.log ( stringIndex(myString, "Joe", 1) ); //10
console.log ( stringIndex(myString, "Joe", "last") ); //38
console.log ( stringIndex(myString, "Joe", 5) ); //[]
于 2021-03-11T23:26:43.510 に答える
0

すべての返信に感謝します。私はそれらすべてを調べて、「針」部分文字列の各出現の最初の最後のインデックスを与える関数を思いつきました。誰かに役立つ場合に備えて、ここに投稿しています。

各オカレンスの最初だけの元のリクエストと同じではないことに注意してください。針の長さを維持する必要がないため、私のユースケースにより適しています。

function findRegexIndices(text, needle, caseSensitive){
  var needleLen = needle.length,
    reg = new RegExp(needle, caseSensitive ? 'gi' : 'g'),
    indices = [],
    result;

  while ( (result = reg.exec(text)) ) {
    indices.push([result.index, result.index + needleLen]);
  }
  return indices
}
于 2019-06-11T14:12:34.893 に答える
-1

以下のコードはあなたのために仕事をします:

function indexes(source, find) {
  var result = [];
  for(i=0;i<str.length; ++i) {
    // If you want to search case insensitive use 
    // if (source.substring(i, i + find.length).toLowerCase() == find) {
    if (source.substring(i, i + find.length) == find) {
      result.push(i);
    }
  }
  return result;
}

indexes("hello, how are you", "ar")
于 2014-08-28T09:31:05.043 に答える
-1
function countInString(searchFor,searchIn){

 var results=0;
 var a=searchIn.indexOf(searchFor)

 while(a!=-1){
   searchIn=searchIn.slice(a*1+searchFor.length);
   results++;
   a=searchIn.indexOf(searchFor);
 }

return results;

}
于 2013-02-27T22:22:46.530 に答える
-2

String.prototype.matchを使用します。

MDN ドキュメント自体の例を次に示します。

var str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
var regexp = /[A-E]/gi;
var matches_array = str.match(regexp);

console.log(matches_array);
// ['A', 'B', 'C', 'D', 'E', 'a', 'b', 'c', 'd', 'e']
于 2017-01-12T09:56:20.293 に答える