문자열에서 n 번째 발생을 얻는 방법?


104

다음과 같이 2nd발생 시작 위치를 얻고 ABC싶습니다.

var string = "XYZ 123 ABC 456 ABC 789 ABC";
getPosition(string, 'ABC', 2) // --> 16

어떻게 하시겠습니까?


두 번째 발생 또는 마지막? :)
Ja͢ck 2013-01-23

혼란을 드려 죄송합니다. 마지막 색인을 찾고 있지 않습니다. nth이 경우 두 번째 발생 시작 위치를 찾고 있습니다.
Adam

답변:


158

const string = "XYZ 123 ABC 456 ABC 789 ABC";

function getPosition(string, subString, index) {
  return string.split(subString, index).join(subString).length;
}

console.log(
  getPosition(string, 'ABC', 2) // --> 16
)


26
사실이 답변이 마음에 들지 않습니다. 무제한 길이 입력이 주어지면 불필요하게 무제한 길이 배열을 생성 한 다음 대부분을 버립니다. 그것은보다 신속하고 효율적으로 반복적으로는 사용 만하는 것 fromIndex에 인수String.indexOf
알니 타크

3
function getPosition(str, m, i) { return str.split(m, i).join(m).length; }
복사

9
각 매개 변수가 의미하는 바를 지정했다면 좋았을 것입니다.
Foreever

1
나는 단순히 OP에 의해 정의 된 기능을 구현했습니다 @Foreever
데니스 Séguret을

5
< i발생하는 경우 문자열의 길이를 제공합니다 m. 즉, getPosition("aaaa","a",5)제공 4등의 수행, getPosition("aaaa","a",72)! 이 경우 -1을 원한다고 생각합니다. var ret = str.split(m, i).join(m).length; return ret >= str.length ? -1 : ret;또한 캐치 될 가능성 i <= 0return ret >= str.length || i <= 0 ? -1 : ret;
러핀

70

배열을 만들지 않고 indexOf 문자열을 사용할 수도 있습니다.

두 번째 매개 변수는 다음 일치 항목을 찾기 시작하는 색인입니다.

function nthIndex(str, pat, n){
    var L= str.length, i= -1;
    while(n-- && i++<L){
        i= str.indexOf(pat, i);
        if (i < 0) break;
    }
    return i;
}

var s= "XYZ 123 ABC 456 ABC 789 ABC";

nthIndex(s,'ABC',3)

/*  returned value: (Number)
24
*/

길이 캐싱과 String 프로토 타입을 확장하지 않기 때문에이 버전을 좋아합니다.
Christophe Roussy

8
jsperf 에 따르면 이 방법은 허용 된 답변보다 훨씬 빠릅니다
boop

증분은 i덜 혼란스럽게 만들 수 있습니다.var i; for (i = 0; n > 0 && i !== -1; n -= 1) { i = str.indexOf(pat, /* fromIndex */ i ? (i + 1) : i); } return i;
hlfcoding

1
나는 존재하지 않는 두 번째 인스턴스를 테스트했을 때 다른 대답이 -1을 반환 한 첫 번째 문자열의 길이를 반환했기 때문에 수락 된 대답보다 이것을 선호합니다 . 찬성 투표하고 감사합니다.
John

2
이것이 JS의 내장 기능이 아니라는 것은 어리석은 일입니다.
Sinister Beard

20

kennebec의 답변을 바탕으로 n 번째 발생이 0이 아닌 -1을 반환하는 프로토 타입 함수를 만들었습니다.

String.prototype.nthIndexOf = function(pattern, n) {
    var i = -1;

    while (n-- && i++ < this.length) {
        i = this.indexOf(pattern, i);
        if (i < 0) break;
    }

    return i;
}

2
결코 이제까지 실수로이 프로토 타입에 의해 덮어 쓰기 될 수있는 기본적 기능의 최종 적응으로 낙타 표기법을 사용하지 않습니다. 이 경우 소문자와 밑줄 (URL의 대시)을 모두 권장합니다 String.prototype.nth_index_of.. 당신이 당신의 이름이 독특하고 충분히 미쳤다고 생각하더라도 세상은 그것이 더 미쳤을 수 있고 할 것임을 증명할 것입니다.
John

특히 프로토 타이핑을 할 때. 물론, 아무도 당신이 나쁜 습관을 만들도록 허용함으로써 특정 메소드 이름을 사용하지 않을 것 입니다. 다른 중요한 예 : SQL 을 수행 할 때 항상 데이터를 묶어 작은 따옴표 해킹으로부터 보호 하지 않습니다 . 전문적인 코딩의 대부분은 좋은 습관을 갖는 것이 아니라 그러한 습관이 왜 중요한지 이해 하는 것입니다. :-)INSERTmysqli_real_escape_string
John

1
문자열 프로토 타입을 확장하지 마십시오.

4

재귀가 항상 답이기 때문입니다.

function getPosition(input, search, nth, curr, cnt) {
    curr = curr || 0;
    cnt = cnt || 0;
    var index = input.indexOf(search);
    if (curr === nth) {
        if (~index) {
            return cnt;
        }
        else {
            return -1;
        }
    }
    else {
        if (~index) {
            return getPosition(input.slice(index + search.length),
              search,
              nth,
              ++curr,
              cnt + index + search.length);
        }
        else {
            return -1;
        }
    }
}

1
물결표 (@RenanCoelho ~:) 비트 단위 자바 스크립트에서 NOT 연산자입니다 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
세바스티앙은

2

다음은 n일치 항목이 발견 될 때까지 문자열을 반복하는 솔루션입니다 .

String.prototype.nthIndexOf = function(searchElement, n, fromElement) {
    n = n || 0;
    fromElement = fromElement || 0;
    while (n > 0) {
        fromElement = this.indexOf(searchElement, fromElement);
        if (fromElement < 0) {
            return -1;
        }
        --n;
        ++fromElement;
    }
    return fromElement - 1;
};

var string = "XYZ 123 ABC 456 ABC 789 ABC";
console.log(string.nthIndexOf('ABC', 2));

>> 16

2

이 메서드는 배열에 저장된 n 번째 항목의 인덱스를 호출하는 함수를 만듭니다.

function nthIndexOf(search, n) { 
    var myArray = []; 
    for(var i = 0; i < myString.length; i++) { //loop thru string to check for occurrences
        if(myStr.slice(i, i + search.length) === search) { //if match found...
            myArray.push(i); //store index of each occurrence           
        }
    } 
    return myArray[n - 1]; //first occurrence stored in index 0 
}

위의 코드에서 myString을 정의했다고 생각하지 않으며 myStr === myString?
Seth Eden

1

더 짧고 불필요한 문자열을 만들지 않고 더 쉽게 생각합니다.

const findNthOccurence = (string, nth, char) => {
  let index = 0
  for (let i = 0; i < nth; i += 1) {
    if (index !== -1) index = string.indexOf(char, index + 1)
  }
  return index
}

0

사용 indexOf재귀 :

먼저 전달 된 n 번째 위치가 총 부분 문자열 발생 수보다 큰지 확인합니다. 전달되면 n 번째 인덱스를 찾을 때까지 각 인덱스를 재귀 적으로 살펴 봅니다.

var getNthPosition = function(str, sub, n) {
    if (n > str.split(sub).length - 1) return -1;
    var recursePosition = function(n) {
        if (n === 0) return str.indexOf(sub);
        return str.indexOf(sub, recursePosition(n - 1) + 1);
    };
    return recursePosition(n);
};

0

사용 [String.indexOf][1]

var stringToMatch = "XYZ 123 ABC 456 ABC 789 ABC";

function yetAnotherGetNthOccurance(string, seek, occurance) {
    var index = 0, i = 1;

    while (index !== -1) {
        index = string.indexOf(seek, index + 1);
        if (occurance === i) {
           break;
        }
        i++;
    }
    if (index !== -1) {
        console.log('Occurance found in ' + index + ' position');
    }
    else if (index === -1 && i !== occurance) {
        console.log('Occurance not found in ' + occurance + ' position');
    }
    else {
        console.log('Occurance not found');
    }
}

yetAnotherGetNthOccurance(stringToMatch, 'ABC', 2);

// Output: Occurance found in 16 position

yetAnotherGetNthOccurance(stringToMatch, 'ABC', 20);

// Output: Occurance not found in 20 position

yetAnotherGetNthOccurance(stringToMatch, 'ZAB', 1)

// Output: Occurance not found

0
function getStringReminder(str, substr, occ) {
   let index = str.indexOf(substr);
   let preindex = '';
   let i = 1;
   while (index !== -1) {
      preIndex = index;
      if (occ == i) {
        break;
      }
      index = str.indexOf(substr, index + 1)
      i++;
   }
   return preIndex;
}
console.log(getStringReminder('bcdefgbcdbcd', 'bcd', 3));

-2

StackOverflow에 대한 또 다른 질문에 대해 다음 코드를 가지고 놀았고 여기에 적절할 것이라고 생각했습니다. printList2 함수는 정규식의 사용을 허용하고 모든 발생을 순서대로 나열합니다. (printList는 이전 솔루션의 시도 였지만 여러 경우에 실패했습니다.)

<html>
<head>
<title>Checking regex</title>
<script>
var string1 = "123xxx5yyy1234ABCxxxabc";
var search1 = /\d+/;
var search2 = /\d/;
var search3 = /abc/;
function printList(search) {
   document.writeln("<p>Searching using regex: " + search + " (printList)</p>");
   var list = string1.match(search);
   if (list == null) {
      document.writeln("<p>No matches</p>");
      return;
   }
   // document.writeln("<p>" + list.toString() + "</p>");
   // document.writeln("<p>" + typeof(list1) + "</p>");
   // document.writeln("<p>" + Array.isArray(list1) + "</p>");
   // document.writeln("<p>" + list1 + "</p>");
   var count = list.length;
   document.writeln("<ul>");
   for (i = 0; i < count; i++) {
      document.writeln("<li>" +  "  " + list[i] + "   length=" + list[i].length + 
          " first position=" + string1.indexOf(list[i]) + "</li>");
   }
   document.writeln("</ul>");
}
function printList2(search) {
   document.writeln("<p>Searching using regex: " + search + " (printList2)</p>");
   var index = 0;
   var partial = string1;
   document.writeln("<ol>");
   for (j = 0; j < 100; j++) {
       var found = partial.match(search);
       if (found == null) {
          // document.writeln("<p>not found</p>");
          break;
       }
       var size = found[0].length;
       var loc = partial.search(search);
       var actloc = loc + index;
       document.writeln("<li>" + found[0] + "  length=" + size + "  first position=" + actloc);
       // document.writeln("  " + partial + "  " + loc);
       partial = partial.substring(loc + size);
       index = index + loc + size;
       document.writeln("</li>");
   }
   document.writeln("</ol>");

}
</script>
</head>
<body>
<p>Original string is <script>document.writeln(string1);</script></p>
<script>
   printList(/\d+/g);
   printList2(/\d+/);
   printList(/\d/g);
   printList2(/\d/);
   printList(/abc/g);
   printList2(/abc/);
   printList(/ABC/gi);
   printList2(/ABC/i);
</script>
</body>
</html>

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.