جاوا: شمارش تعداد کلمات در رشته

معرفی

شمارش تعداد تکرار کلمات در یک رشته کار نسبتاً آسانی است، اما چندین روش برای انجام این کار دارد. شما باید کارایی روش را نیز در نظر بگیرید، زیرا معمولاً زمانی که نمی‌خواهید کار دستی انجام دهید - یعنی زمانی که فضای جستجو بزرگ است، می‌خواهید از ابزارهای خودکار استفاده کنید.

در این راهنما، نحوه شمارش تعداد تکرار کلمات در یک رشته در جاوا را خواهید آموخت:

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() و عبارات منظم

تعداد کلمات در رشته با String.split()

ساده ترین راه برای شمارش وقوع یک کلمه هدف در یک رشته این است که رشته را بر روی هر کلمه تقسیم کنید و در آرایه تکرار کنید و یک عدد را افزایش دهید. 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

تعداد کلمات در رشته با Collections.frequency()

La Collections.frequency() روش پیاده سازی بسیار تمیزتر و سطح بالاتری را ارائه می دهد که یک ساده را انتزاع می کند for حلقه، و هویت هر دو را بررسی می کند (خواه یک شی is یک شی دیگر) و برابری (اینکه آیا یک شی با یک شیء دیگر برابر است، بسته به ویژگی های کیفی آن شی).

La 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

وقوع کلمه در رشته با تطبیق (عبارات منظم - RegEx)

در نهایت، می توانید از Regular Expressions برای جستجوی الگوها و شمارش تعداد الگوهای منطبق استفاده کنید. عبارات منظم برای این کار ساخته شده اند، بنابراین برای این کار مناسب است. در جاوا، Pattern کلاس برای نشان دادن و کامپایل عبارات منظم و the Matcher class برای یافتن و مطابقت الگوها استفاده می شود.

با استفاده از 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 را با بهترین روش ها، استانداردهای پذیرفته شده در صنعت و برگه تقلب شامل بررسی کنید. دستورات Google Git را متوقف کنید و در واقع یاد گرفتن آی تی!

حال، اگر بخواهیم «سلام» یا «جهان» را جستجو کنیم، تعداد موارد منطبق بسیار بیشتر از دو مورد قبلی خواهد بود. روش های ما اکنون در معیار چگونه عمل می کنند؟

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

در حال حاضر، تقسیم آرایه سریعتر ظاهر می شود! به طور کلی، معیارها به عوامل مختلفی بستگی دارند - مانند فضای جستجو، کلمه هدف، و غیره و مورد استفاده شخصی شما ممکن است با معیار متفاوت باشد.

مشاوره: روش ها را روی متن خود امتحان کنید، زمان ها را یادداشت کنید و کارآمدترین و زیباترین روش را برای خود انتخاب کنید.

نتیجه

در این راهنمای کوتاه، ما نگاهی به نحوه شمارش وقوع کلمات برای یک کلمه هدف، در یک رشته در جاوا انداخته‌ایم. ما کار را با تقسیم رشته و استفاده از یک شمارنده ساده شروع کرده‌ایم و سپس از آن استفاده می‌کنیم Collections کلاس کمکی و در نهایت با استفاده از Regular Expressions.

در پایان، ما روش‌ها را محک زده‌ایم و خاطرنشان کردیم که عملکرد خطی نیست و به فضای جستجو بستگی دارد. برای متون ورودی طولانی تر با تطابق زیاد، به نظر می رسد تقسیم آرایه ها بیشترین کارایی را دارند. هر سه روش را به تنهایی امتحان کنید و بهترین را انتخاب کنید.

تمبر زمان:

بیشتر از Stackabuse