Bir dizede n'inci oluşum nasıl elde edilir?


104

Şunun gibi bir şeyle 2ndoluşumunun başlangıç ​​pozisyonunu almak ABCistiyorum:

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

Nasıl yapardın?


İkinci olay mı yoksa sonuncusu mu? :)
Ja͢ck

Karışıklık için üzgünüm, son dizini aramıyorum. nthOluşun başlangıç ​​pozisyonunu arıyorum , bu durumda ikinci.
Adam Halasz

Yanıtlar:


159

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
)


27
Aslında bu cevabı beğenmedim. Sınırsız uzunluk girdisi verildiğinde, gereksiz yere sınırsız uzunluk dizisi oluşturur ve sonra çoğunu atar. fromIndexArgümanı yinelemeli olarak kullanmak daha hızlı ve daha verimli olacaktırString.indexOf
Alnitak

4
function getPosition(str, m, i) { return str.split(m, i).join(m).length; }
kopyası

9
Her parametrenin ne anlama geldiğini belirtirseniz iyi olurdum.
Foreever

1
@Foreever Ben sadece OP
Denys Séguret

5
< iOluşumu varsa bu size dizenin uzunluğunu verecektir m. Yani, getPosition("aaaa","a",5)veren 4olarak yapar getPosition("aaaa","a",72)! Sanırım bu durumlarda -1 istiyorsunuz. var ret = str.split(m, i).join(m).length; return ret >= str.length ? -1 : ret;Ayrıca av isteyebilirsiniz i <= 0ilereturn ret >= str.length || i <= 0 ? -1 : ret;
Ruffin

70

Herhangi bir dizi oluşturmadan da indexOf dizesini kullanabilirsiniz.

İkinci parametre, bir sonraki eşleşmeyi aramaya başlamak için indekstir.

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
*/

Bu sürümü uzunluk önbelleğe alma ve String prototipini genişletmemesi nedeniyle seviyorum.
Christophe Roussy

8
göre jsperf bu yöntemi daha hızlı kabul cevap daha yoludur
boop

' ivar i; for (i = 0; n > 0 && i !== -1; n -= 1) { i = str.indexOf(pat, /* fromIndex */ i ? (i + 1) : i); } return i;
Nin artırılması

1
Bunu kabul edilene tercih ederim var olmayan ikinci bir örnek için test ettiğimde, diğer yanıtın -1 döndürdüğü ilk dizenin uzunluğunu döndürdüğü yanıta . Bir oylama ve teşekkür ederim.
John

2
Bunun JS'nin yerleşik bir özelliği olmaması saçma.
Uğursuz Sakal

20

Kennedy'nin cevabından yola çıkarak, n'inci oluşum 0 yerine bulunmazsa -1 döndürecek bir prototip işlevi yarattım.

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
Hiçbir zaman hiç istemeden bu prototip tarafından üzerine yazılır haline gelebilir doğal özelliklerinden nihai uyarlaması olarak camelCase kullanın. Bu durumda ben (URL'ler için tire) hepsi küçük harf ve alt çizgi öneriyoruz: String.prototype.nth_index_of. Adınızın benzersiz ve yeterince çılgın olduğunu düşünseniz bile, dünya onun daha çılgın yapabileceğini ve yapacağını kanıtlayacaktır.
John

Özellikle prototipleme yaparken. Elbette, kötü bir alışkanlık yarattığınızı kendinize yapmanıza izin vererek , hiç kimse bu belirli yöntem adını kullanamaz . Farklı bir kritik örnek olsa: daima enclose veriler SQL yaparken INSERTolarak mysqli_real_escape_stringyok değil tek tırnak kesmek karşı koruma sağlar. Profesyonel kodlamanın çoğu, sadece iyi alışkanlıklara sahip olmakla kalmaz, aynı zamanda bu tür alışkanlıkların neden önemli olduğunu da anlamaktır . :-)
John

2
Dize prototipini genişletmeyin.

4

Çünkü özyineleme her zaman cevaptır.

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 tilde ( ~), JavaScript'teki bitsel NOT operatörüdür: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Sébastien

3

İşte benim çözümüm, neşleşmeler bulunana kadar dize üzerinde yineleniyor :

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

Bu yöntem, bir dizide depolanan n'inci oluşumların dizinini çağıran bir işlev oluşturur

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 
}

Yukarıdaki kodda myString'i tanımladığınızı sanmıyorum ve myStr === myString mi?
Seth Eden

1

Gereksiz dizeler oluşturmadan daha kısa yol ve daha kolay düşünüyorum.

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

Kullanma indexOfve Özyineleme :

İlk olarak, geçilen n'inci konumun toplam alt dize oluşumu sayısından daha büyük olup olmadığını kontrol edin. Geçilirse, n'inci bulunana kadar her dizini yinelemeli olarak gözden geçirin.

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

Kullanma [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'da başka bir soru için aşağıdaki kodla oynuyordum ve burası için uygun olabileceğini düşündüm. PrintList2 işlevi bir düzenli ifadenin kullanımına izin verir ve tüm oluşumları sırayla listeler. (printList, daha önceki bir çözüme yönelik bir girişimdi, ancak bazı durumlarda başarısız oldu.)

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.