जावा: स्ट्रिंग में शब्द घटना की संख्या की गणना करें

परिचय

एक स्ट्रिंग में शब्दों की घटनाओं की संख्या की गणना करना काफी आसान काम है, लेकिन ऐसा करने के कई तरीके हैं। आपको विधि की दक्षता का भी हिसाब देना होगा, क्योंकि जब आप मैन्युअल श्रम नहीं करना चाहते हैं - यानी जब खोज स्थान बड़ा होता है, तो आप आमतौर पर स्वचालित उपकरणों को नियोजित करना चाहते हैं।

इस गाइड में, आप सीखेंगे कि जावा में एक स्ट्रिंग में शब्दों की संख्या की गणना कैसे करें:

String searchText = "Your body may be chrome, but the heart never changes. It wants what it wants.";
String targetWord = "wants";

हम की घटनाओं की संख्या की खोज करेंगे targetWord, का उपयोग करते हुए String.split(), Collections.frequency() और नियमित अभिव्यक्ति।

के साथ स्ट्रिंग में शब्द अवसरों की गणना करें स्ट्रिंग.स्प्लिट ()

एक स्ट्रिंग में एक लक्ष्य शब्द की घटना को गिनने का सबसे सरल तरीका है कि प्रत्येक शब्द पर स्ट्रिंग को विभाजित किया जाए, और सरणी के माध्यम से पुनरावृति की जाए, wordCount प्रत्येक मैच पर। ध्यान दें कि जब किसी शब्द के चारों ओर किसी प्रकार का विराम चिह्न हो, जैसे कि wants. वाक्य के अंत में - सरल शब्द-स्तरीय विभाजन सही ढंग से व्यवहार करेगा wants और wants. अलग शब्दों के रूप में!

इसे हल करने के लिए, आप वाक्य से सभी विराम चिह्नों को आसानी से हटा सकते हैं से पहले इसे विभाजित करना:

String[] words = searchText.replaceAll("p{Punct}", "").split(" ");

int wordCount = 0;
for (int i=0; i < words.length; i++)
    if (words[i].equals(targetWord))
        wordCount++;
System.out.println(wordCount);

में for लूप, हम केवल सरणी के माध्यम से पुनरावृति करते हैं, यह जाँचते हुए कि क्या प्रत्येक सूचकांक में तत्व बराबर है targetWord. यदि ऐसा है, तो हम वृद्धि करते हैं wordCount, जो निष्पादन के अंत में प्रिंट करता है:

2

के साथ स्ट्रिंग में शब्द अवसरों की गणना करें संग्रह। आवृत्ति ()

RSI Collections.frequency() विधि एक बहुत साफ, उच्च-स्तरीय कार्यान्वयन प्रदान करती है, जो एक सरल को दूर करती है for लूप, और दोनों पहचान के लिए जाँच करता है (चाहे कोई वस्तु हो) is एक अन्य वस्तु) और समानता (क्या कोई वस्तु किसी अन्य वस्तु के बराबर है, उस वस्तु की गुणात्मक विशेषताओं के आधार पर)।

RSI frequency() विधि के माध्यम से खोजने के लिए एक सूची को स्वीकार करता है, और लक्ष्य वस्तु, और अन्य सभी वस्तुओं के लिए भी काम करता है, जहां व्यवहार इस बात पर निर्भर करता है कि वस्तु स्वयं कैसे लागू होती है equals(). तार के मामले में, equals() के लिए जाँच करता है स्ट्रिंग की सामग्री:


searchText = searchText.replaceAll("p{Punct}", "");

int wordCount = Collections.frequency(Arrays.asList(searchText.split(" ")), targetWord);
System.out.println(wordCount);

यहाँ, हमने से प्राप्त सरणी को रूपांतरित किया है split() एक जावा में ArrayList, सहायक का उपयोग करना asList() की विधि Arrays कक्षा। कमी ऑपरेशन frequency() की आवृत्ति को दर्शाने वाला एक पूर्णांक देता है targetWord सूची में, और इसमें परिणाम:

2

स्ट्रिंग में शब्द घटनाएँ . के साथ मैचर (रेगुलर एक्सप्रेशन - रेगेक्स)

अंत में, आप पैटर्न खोजने के लिए रेगुलर एक्सप्रेशन का उपयोग कर सकते हैं, और मिलान किए गए पैटर्न की संख्या की गणना कर सकते हैं। इसके लिए रेगुलर एक्सप्रेशन बनाए जाते हैं, इसलिए यह कार्य के लिए बहुत स्वाभाविक है। जावा में, Pattern क्लास का उपयोग रेगुलर एक्सप्रेशन को दर्शाने और संकलित करने के लिए किया जाता है, और Matcher वर्ग का उपयोग पैटर्न खोजने और मिलान करने के लिए किया जाता है।

RegEx का उपयोग करते हुए, हम विराम चिह्न इनवेरियन को अभिव्यक्ति में ही कोड कर सकते हैं, इसलिए स्ट्रिंग को बाहरी रूप से प्रारूपित करने या विराम चिह्न को हटाने की कोई आवश्यकता नहीं है, जो बड़े ग्रंथों के लिए बेहतर है जहां स्मृति में एक और परिवर्तित संस्करण संग्रहीत करना महंगा हो सकता है:

Pattern pattern = Pattern.compile("b%s(?!w)".format(targetWord));

Pattern pattern = Pattern.compile("bwants(?!w)");
Matcher matcher = pattern.matcher(searchText);

int wordCount = 0;
while (matcher.find())
    wordCount++;

System.out.println(wordCount);

यह भी परिणाम है:

2

दक्षता बेंचमार्क

तो, सबसे कुशल कौन सा है? आइए एक छोटा बेंचमार्क चलाएं:

int runs = 100000;

long start1 = System.currentTimeMillis();
for (int i = 0; i < runs; i++) {
    int result = countOccurencesWithSplit(searchText, targetWord);
}

long end1 = System.currentTimeMillis();
System.out.println(String.format("Array split approach took: %s miliseconds", end1-start1));

long start2 = System.currentTimeMillis();
  for (int i = 0; i < runs; i++) {
    int result = countOccurencesWithCollections(searchText, targetWord);
}

long end2 = System.currentTimeMillis();
System.out.println(String.format("Collections.frequency() approach took: %s miliseconds", end2-start2));

long start3 = System.currentTimeMillis();
for (int i = 0; i < runs; i++) {
    int result = countOccurencesWithRegex(searchText, targetWord);
}

long end3 = System.currentTimeMillis();
System.out.println(String.format("Regex approach took: %s miliseconds", end3-start3));

प्रत्येक विधि को 100000 बार चलाया जाएगा (संख्या जितनी अधिक होगी, विचरण उतना ही कम होगा और संयोग के कारण परिणाम, बड़ी संख्या के नियम के कारण)। इस कोड को चलाने का परिणाम है:

Array split approach took: 152 miliseconds
Collections.frequency() approach took: 140 miliseconds
Regex approach took: 92 miliseconds

हालाँकि - क्या होता है यदि हम खोज को बड़ा बनाकर कम्प्यूटेशनल रूप से अधिक महंगा बनाते हैं? आइए एक सिंथेटिक वाक्य उत्पन्न करें:

List possibleWords = Arrays.asList("hello", "world ");
StringBuffer searchTextBuffer = new StringBuffer();

for (int i = 0; i < 100; i++) {
    searchTextBuffer.append(String.join(" ", possibleWords));
}
System.out.println(searchTextBuffer);

यह सामग्री के साथ एक स्ट्रिंग बनाता है:

hello world hello world hello world hello ...

सर्वोत्तम प्रथाओं, उद्योग-स्वीकृत मानकों और शामिल चीट शीट के साथ, Git सीखने के लिए व्यावहारिक मार्गदर्शिका देखें। Googling Git कमांड को रोकें और वास्तव में सीखना यह!

अब, यदि हम "हैलो" या "वर्ल्ड" में से किसी एक को खोजते हैं - तो पहले से दोनों की तुलना में कई अधिक मैच होंगे। बेंचमार्क में अब हमारे तरीके कैसे काम करते हैं?

Array split approach took: 606 miliseconds
Collections.frequency() approach took: 899 miliseconds
Regex approach took: 801 miliseconds

अब, सरणी विभाजन सबसे तेजी से सामने आता है! सामान्य तौर पर, बेंचमार्क विभिन्न कारकों पर निर्भर करते हैं - जैसे कि खोज स्थान, लक्ष्य शब्द, आदि और आपका व्यक्तिगत उपयोग मामला बेंचमार्क से भिन्न हो सकता है।

सलाह: अपने स्वयं के पाठ पर विधियों को आज़माएं, समय नोट करें, और अपने लिए सबसे कुशल और सुरुचिपूर्ण चुनें।

निष्कर्ष

इस संक्षिप्त मार्गदर्शिका में, हमने जावा में एक स्ट्रिंग में, लक्ष्य शब्द के लिए शब्द आवृत्ति की गणना करने के तरीके पर एक नज़र डाली है। हमने स्ट्रिंग को विभाजित करके और एक साधारण काउंटर का उपयोग करके शुरू किया है, इसके बाद का उपयोग किया है Collections हेल्पर क्लास, और अंत में, रेगुलर एक्सप्रेशंस का उपयोग करना।

अंत में, हमने विधियों को बेंचमार्क किया है, और ध्यान दिया है कि प्रदर्शन रैखिक नहीं है, और खोज स्थान पर निर्भर करता है। कई मैचों के साथ लंबे इनपुट टेक्स्ट के लिए, स्प्लिटिंग एरे सबसे अधिक प्रदर्शन करने वाले प्रतीत होते हैं। तीनों विधियों को अपने आप आज़माएं, और सबसे अधिक प्रदर्शन करने वाली विधि चुनें।

समय टिकट:

से अधिक स्टैकब्यूज