জাভাস্ক্রিপ্টে অন্য স্ট্রিংয়ের সমস্ত ঘটনার সূচকগুলি কীভাবে খুঁজে পাবেন?


106

আমি অন্য স্ট্রিংয়ের ক্ষেত্রে স্ট্রিংয়ের সমস্ত উপস্থিতির অবস্থানগুলি খুঁজে পাওয়ার চেষ্টা করছি, কেস-সংবেদনশীল।

উদাহরণস্বরূপ, স্ট্রিং দেওয়া:

আমি লেবাননে উকুলি খেলতে শিখেছি।

এবং অনুসন্ধানের স্ট্রিং le, আমি অ্যারেটি পেতে চাই:

[2, 25, 27, 33]

উভয় স্ট্রিংই ভেরিয়েবল হবে - যেমন, আমি তাদের মানগুলি হার্ড-কোড করতে পারি না।

আমি অনুভব করেছি যে এটি নিয়মিত প্রকাশের জন্য একটি সহজ কাজ, তবে কাজ করার জন্য এটি খুঁজে পেতে কিছুক্ষণ লড়াই করার পরে আমার ভাগ্য হত না।

আমি কীভাবে এটি ব্যবহার করে এটি সম্পাদন করতে পারি তার উদাহরণটি পেয়েছি .indexOf(), তবে এটি করার আরও একটি সংক্ষিপ্ত উপায় থাকতে হবে?

উত্তর:


167
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এমনটি মোকাবেলায় আমি অন্য সংস্করণ লিখেছি যাতে আপনি যেখানে শুরু করেছিলেন সেখানে ফিরে এসেছেন। মন্তব্যগুলিতে উইককেনের দ্বারা নির্দেশিত হিসাবে, নিয়মিত প্রকাশের সাথে সাধারণ ক্ষেত্রে এটি করার জন্য আপনাকে বিশেষ রেজেক্স অক্ষরগুলি থেকে বাঁচতে হবে, এমন পর্যায়ে আমি মনে করি রেজেক্স সমাধানটি তার মূল্যবোধের চেয়ে মাথাব্যথার কারণ হয়ে ওঠে।

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>


4
কিভাবে leএখানে একটি পরিবর্তনশীল স্ট্রিং হবে? এমনকি new Regexp(str);বিশেষ চরিত্রগুলির বিপদ ব্যবহারের সময় লুকিয়ে থাকে, $2.50উদাহরণস্বরূপ অনুসন্ধান করা হয়। এরকম কিছু regex = new Regexp(dynamicstring.replace(/([\\.+*?\\[^\\]$(){}=!<>|:])/g, '\\$1'));আরও কাছের আইএমএইচও হবে। আমি নিশ্চিত নই যে জেএস-এ বিল্ট-ইন রেজেক্স পলান প্রক্রিয়া রয়েছে কিনা।
রিক্কেন

new RegExp(searchStr)উপায় হবে, এবং হ্যাঁ, সাধারণ ক্ষেত্রে আপনাকে বিশেষ চরিত্রগুলি থেকে বাঁচতে হবে। আপনার যদি সেই সাধারণতার স্তরের প্রয়োজন না হয় তবে তা করা সত্য নয়।
টিম ডাউন

4
দুর্দান্ত উত্তর, এবং খুব সহায়ক। অনেক ধন্যবাদ, টিম!
চরম বিশৃঙ্খল

4
যদি অনুসন্ধানের স্ট্রিংটি খালি স্ট্রিং হয় তবে আপনি একটি অসীম লুপ পাবেন ... এটির জন্য একটি চেক করা হবে।
হেল্পমিস্ট্যাক ওভারফ্লো মাইঅনলি হপ

4
ধরুন searchStr=aaaএবং যে str=aaaaaa। তারপরে 4 টি ইভেন্ট অনুসন্ধান করার পরিবর্তে আপনার কোডটি কেবল 2 টি খুঁজে পাবে কারণ আপনি searchStr.lengthলুপের মাধ্যমে এড়িয়ে চলেছেন ।
10:30 এ ব্লেজ

19

এখানে রেইজেক্স ফ্রি সংস্করণ রয়েছে:

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

সম্পাদনা করুন : এবং আপনি যদি 'আআআ' এবং 'আ' এর মতো স্ট্রিংগুলি মিল করতে চান তবে [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;
}

7
+1 রেজেক্স ব্যবহার করে সমাধানের বিপরীতে তুলনা করার জন্য আমি কয়েকটি পরীক্ষা চালিয়েছি। সবচেয়ে দ্রুততম পদ্ধতিটি ছিল রেজেজ
StuR

4
দ্রুততম পদ্ধতিটি সূচকগুলি jsperf.com/find-o-substrings
ইথান

@ লিথান কেবলমাত্র যদি সেই ফাংশনটি বাধা হয়ে থাকে এবং যদি ইনপুট স্ট্রিং দীর্ঘ হয় তবে তা বিবেচনা করবে।
jcubic

@ জেকিউবিক আপনার সমাধানটি ভাল বলে মনে হচ্ছে তবে একটি ছোট বিভ্রান্তি রয়েছে। যদি আমি এইভাবে ফাংশন কল করি var result = indexes('aaaa', 'aa')? প্রত্যাশিত ফলাফল হওয়া উচিত [0, 1, 2]নাকি [0, 2]?
Cao Mạnh Quang

@ CaoMạnhQuang কোডটি প্রথম ফলাফল দেখছে। আপনি যদি দ্বিতীয়টি চান তবে আপনাকে লুপটি তৈরি করার সময় এবং ভিতরে রেখে অন্যটি তৈরি করতে i+=find.length;হবেi++
jcubic

15

আপনি অবশ্যই এটি করতে পারেন!

//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ফলাফলের অ্যারেতে ধাক্কা দিতে পারেন ...

সম্পাদনা করুন: লিঙ্ক যুক্ত করা হচ্ছে

@ টিম ডাউন এর উত্তরে রেজাইপ এক্সপেক্স () থেকে প্রাপ্ত ফলাফলগুলি ব্যবহার করা হয়েছে, এবং আমার সমস্ত জাভাস্ক্রিপ্ট সংস্থান এর ব্যবহারের জন্য গ্লোস করে (আপনাকে ম্যাচিং স্ট্রিং দেওয়া বাদ দিয়ে)। সুতরাং তিনি যখন ব্যবহার করেন result.index, এটি একরকম নামবিহীন ম্যাচ অবজেক্ট। ইন Exec এর এমডিসি বিবরণ , তারা আসলে শালীন বিস্তারিতভাবে এই বস্তুর বর্ণনা করে।


হা! যে কোনও ক্ষেত্রে অবদানের জন্য ধন্যবাদ - আমি এটির প্রশংসা করি!
চরম বিশৃঙ্খল

10

ওয়ান লাইনার String.protype.matchAll(ES2020) ব্যবহার করে :

[...sourceStr.matchAll(new RegExp(searchStr, 'gi'))].map(a => a.index)

আপনার মান ব্যবহার করে:

const sourceStr = 'I learned to play the Ukulele in Lebanon.';
const searchStr = 'le';
const indexes = [...sourceStr.matchAll(new RegExp(searchStr, 'gi'))].map(a => a.index);
console.log(indexes); // [2, 25, 27, 33]

আপনি যদি একটি স্প্রেড এবং map()এক লাইনে করতে উদ্বিগ্ন হন তবে আমি এটি for...ofএক মিলিয়ন পুনরাবৃত্তির জন্য লুপ দিয়ে চালিয়েছি (আপনার স্ট্রিং ব্যবহার করে)। for...ofআমার মেশিনে 1150ms গড়ে এক লাইনারের গড় গড় 1420ms হয়। এটি কোনও তাত্পর্যপূর্ণ তাত্পর্য নয়, তবে যদি আপনি কেবল হাতে গোনা কয়েকটি ম্যাচ করে থাকেন তবে এক লাইনার ভালভাবে কাজ করবে।

matchAllক্যানিউজ দেখুন


4

আপনি যদি কেবল সমস্ত ম্যাচের অবস্থান সন্ধান করতে চান তবে আমি আপনাকে একটি সামান্য হ্যাকের দিকে নির্দেশ করতে চাই:

var haystack = 'I learned to play the Ukulele in Lebanon.',
    needle = 'le',
    splitOnFound = haystack.split(needle).map(function (culm)
    {
        return this.pos += culm.length + needle.length
    }, {pos: -needle.length}).slice(0, -1); // {pos: ...} – Object wich is used as this

console.log(splitOnFound);

আপনার যদি ভেরিয়েবল দৈর্ঘ্যের সাথে একটি রেজিপ্স থাকে তবে এটি কিছু ক্ষেত্রে সহায়ক হতে পারে app

এটি কেস সেনসিটিভ। ক্ষেত্রে সংবেদনশীলতা String.toLowerCaseপূর্বে ফাংশন ব্যবহার করুন ।


আমি মনে করি আপনার উত্তরটি সবচেয়ে ভাল, কারণ RegExp ব্যবহার বিপজ্জনক।
ভারত

1

এখানে একটি সাধারণ কোড স্নিপেট:

function getIndexOfSubStr(str, searchToken, preIndex, output) {
    var result = str.match(searchToken);
    if (result) {
        output.push(result.index +preIndex);
        str=str.substring(result.index+searchToken.length);
        getIndexOfSubStr(str, searchToken, preIndex, output)
    }
    return output;
}

var str = "my name is 'xyz' and my school name is 'xyz' and my area name is 'xyz' ";
var searchToken ="my";
var preIndex = 0;

console.log(getIndexOfSubStr(str, searchToken, preIndex, []));


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
}

0

এই সমাধানটি পরীক্ষা করুন যা একই অক্ষরের স্ট্রিংটি খুব সন্ধান করতে সক্ষম হবে, কিছু অনুপস্থিত বা সঠিক না থাকলে আমাকে জানান।

function indexes(source, find) {
    if (!source) {
      return [];
    }
    if (!find) {
        return source.split('').map(function(_, i) { return i; });
    }
    source = source.toLowerCase();
    find = find.toLowerCase();
    var result = [];
    var i = 0;
    while(i < source.length) {
      if (source.substring(i, i + find.length) == find)
        result.push(i++);
      else
        i++
    }
    return result;
  }
  console.log(indexes('aaaaaaaa', 'aaaaaa'))
  console.log(indexes('aeeaaaaadjfhfnaaaaadjddjaa', 'aaaa'))
  console.log(indexes('wordgoodwordgoodgoodbestword', 'wordgood'))
  console.log(indexes('I learned to play the Ukulele in Lebanon.', 'le'))


0

আমি পার্টিতে কিছুটা দেরি করেছি (প্রায় 10 বছর, 2 মাসের মধ্যে), তবে ভবিষ্যতের কোডারদের জন্য একটি উপায় লুপটি ব্যবহার করে এটি করা এবং indexOf()

let haystack = "I learned to play the Ukulele in Lebanon.";
let needle = "le";
let pos = 0; // Position Ref
let result = []; // Final output of all index's.
let hayStackLower = haystack.toLowerCase();

// Loop to check all occurrences 
while (hayStackLower.indexOf(needle, pos) != -1) {
  result.push(hayStackLower.indexOf(needle , pos));
  pos = hayStackLower.indexOf(needle , pos) + 1;
}

console.log("Final ", result); // Returns all indexes or empty array if not found

0

@ জ্যাকুবিকের উত্তরটি অনুসরণ করুন, তার সমাধানটি আমার ক্ষেত্রে একটি সামান্য বিভ্রান্তির
কারণ ঘটেছে উদাহরণস্বরূপ পরিবর্তে var result = indexes('aaaa', 'aa')ফিরে আসবে তাই আমি আমার সমাধানের সাথে মিলে যাওয়ার জন্য তার সমাধানটি কিছুটা আপডেট করেছি[0, 1, 2][0, 2]

function indexes(text, subText, caseSensitive) {
    var _source = text;
    var _find = subText;
    if (caseSensitive != true) {
        _source = _source.toLowerCase();
        _find = _find.toLowerCase();
    }
    var result = [];
    for (var i = 0; i < _source.length;) {
        if (_source.substring(i, i + _find.length) == _find) {
            result.push(i);
            i += _find.length;  // found a subText, skip to next position
        } else {
            i += 1;
        }
    }
    return result;
}

0

আমি টিমের উত্তরটি সুপারিশ করব। যাইহোক, @ ব্লাজের এই মন্তব্যটি বলেছে "ধরুন সার্চএসআরটি = আআ এবং সেই স্ট্রিম = আআআআআ। তারপরে 4 টি সন্ধানের পরিবর্তে আপনার কোডটি কেবল 2 টি খুঁজে পাবে কারণ আপনি লুপে সার্চস্ট্রেলেথ দ্বারা স্কিপ তৈরি করছেন।", যা সত্য টিমের কোড দেখে এখানে বিশেষত এই লাইনটি দেখুন: startIndex = index + searchStrLen;টিমের কোডটি নিজের দৈর্ঘ্যের মধ্যে থাকা স্ট্রিংয়ের কোনও উদাহরণ খুঁজে পাবে না। সুতরাং, আমি টিমের উত্তরটি পরিবর্তন করেছি:

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 indices = getIndicesOf("le", "I learned to play the Ukulele in Lebanon.");

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

+ 1পরিবর্তে এটিকে পরিবর্তন করলে + searchStrLenসূচক 1 সূচকে অ্যারেতে অনুমতি পাবে যদি আমার কাছে aaaaএকটি স্ট্রিং থাকে এবং এর সন্ধানটি থাকে aa

দ্বিতীয় উত্তর

আমার কাছে আরও একটি কোড স্নিপেট রয়েছে যা কাজ করে:

function getIndicesOf(searchStr, str, caseSensitive) {
    var startIndex = 0, index, indices = [];
    if (!caseSensitive) {
        str = str.toLowerCase();
        searchStr = searchStr.toLowerCase();
    }
    for (var i=0; i<str.length-1; i++) {
        if (str.substr(i, searchStr.length) == searchStr) {
            indices.push(i);
        }
    }
    return indices;
}

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

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

যাইহোক, এই স্নিপেটের নেতিবাচক দিকটি হ'ল এটি প্রথমটির তুলনায় কিছুটা বেশি সময় নিতে পারে, যেমন প্রথমটি জাভাস্ক্রিপ্ট অন্তর্নির্মিত ফাংশনটি ব্যবহার করে indexOf(), অন্যদিকে এটি পুরানো উক্তিটির মতো কিছুটা "পুনরায় উদ্ভাবন করা" চাকা। " সুতরাং, সামগ্রিকভাবে, আমি এইটির পরিবর্তে আমার প্রথম উত্তরটি সুপারিশ করব। পিএস যদি কোডটি কীভাবে কাজ করে তা ব্যাখ্যা করতে কোডটিতে কোনও মন্তব্য চান, দয়া করে এটি বলুন, এবং আমি অনুরোধটির প্রতিক্রিয়া জানাতে পেরে খুশি হব।


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

}

এটি নিয়মিত প্রকাশের চেয়ে অন্য স্ট্রিংয়ের মধ্যে স্ট্রিংয়ের উপস্থিতিগুলির সন্ধান করে।

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

-2

স্ট্রিং.প্রোটোটাইপ.ম্যাচ ব্যবহার করুন ।

এখানে নিজেই এমডিএন ডক্সের একটি উদাহরণ রয়েছে:

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

12
প্রশ্নটি কীভাবে ঘটনার সূচকগুলি খুঁজে পাওয়া যায় , সেগুলি নিজেই ঘটে না!
লাকীলুক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.