program tip

문자열 내에서 지정된 문자의 모든 색인 찾기

radiobox 2021. 1. 6. 07:59
반응형

문자열 내에서 지정된 문자의 모든 색인 찾기


예를 들어 내가 "scissors"변수에 있고 문자의 모든 발생 위치를 알고 싶다면 다음과 같이 "s"출력되어야합니다.1, 4, 5, 8

가장 효율적인 방법으로 JavaScript에서 어떻게 할 수 있습니까? 전체를 루핑하는 것이 매우 효율적이라고 생각하지 않습니다.


간단한 루프가 잘 작동합니다.

var str = "scissors";
var indices = [];
for(var i=0; i<str.length;i++) {
    if (str[i] === "s") indices.push(i);
}

이제 1,4,5,8을 원한다고 표시합니다. 인덱스는 0부터 시작하므로 0, 3, 4, 7이됩니다. 따라서 하나를 추가 할 수 있습니다.

if (str[i] === "s") indices.push(i+1);

이제 예상 한 결과를 얻을 수 있습니다.

바이올린은 여기에서 볼 수 있습니다 .

전체를 루핑하는 것이 매우 효율적이라고 생각하지 않습니다.

성능에 관한 한, 문제가 발생할 때까지 심각하게 걱정할 필요가 없다고 생각합니다.

다음은 다양한 답변을 비교 하는 jsPerf 테스트입니다. Safari 5.1에서는 IndexOf가 최고의 성능을 발휘합니다. Chrome 19에서는 for 루프가 가장 빠릅니다.

여기에 이미지 설명 입력


기본 String.prototype.indexOf방법을 사용하여 각 오프셋을 가장 효율적으로 찾습니다.

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]

그러나 이것은 마이크로 최적화입니다. 충분히 빠른 간단하고 간결한 루프의 경우 :

// 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);    

사실, 기본 루프는 indexOf! 를 사용하는 것보다 크롬에서 더 빠릅니다 .

링크의 성능 결과 그래프


기준

내가 모든 것을 벤치마킹했을 때 정규 표현식이 가장 잘 수행되는 것처럼 보였기 때문에 이것을 생각해 냈습니다.

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;
}

넌 할 수있어

indexesOf('ssssss', /s/g);

돌아올 것이다

{s: [0,1,2,3,4,5]}

많은 양의 텍스트에 대해 여러 문자를 일치시키는 매우 빠른 방법이 필요했습니다. 예를 들어 이렇게 할 수 있습니다.

indexesOf('dddddssssss', /s|d/g);

그리고 당신은 이것을 얻을 것입니다

{d:[0,1,2,3,4], s:[5,6,7,8,9,10]}

이렇게하면 한 번에 모든 경기 색인을 얻을 수 있습니다.


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]

JavaScript는 0부터 계산 i합니다. 필요한 경우에 +1을 추가 합니다.


더 많은 기능적 재미와 더 일반적인 : 이것은 문자열에서 길이에 관계없이 하위 문자열의 시작 인덱스를 찾습니다.

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]

자바 스크립트의 match () 함수도 사용할 수 있습니다. 정규식을 만든 다음 매개 변수로 match ()에 전달할 수 있습니다.

stringName.match(/s/g);

이것은 문자 's'의 모든 발생 배열을 반환해야합니다.


나는 질문을 좋아했고 reduce()배열에 정의 된 방법 을 사용하여 내 대답을 작성하려고 생각했습니다 .

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

참조 URL : https://stackoverflow.com/questions/10710345/finding-all-indexes-of-a-specified-character-within-a-string

반응형