У меня есть массив строк.
A=["hello", "you"]
У меня есть строка, скажем
s="hello, hello you are so wonderful"
Мне нужно подсчитать количество вхождений строк из A
в s
. В этом случае число вхождений равно 3 (2 "hello"
, 1 "you"
).
Как это сделать эффективно? (A
может содержать много слов, и s
может быть длительным на практике)
public void countMatches() {
String[] A = {"hello", "you"};
String s = "hello, hello you are so wonderful";
String patternString = "(" + StringUtils.join(A, "|") + ")";
Pattern pattern = Pattern.compile(patternString);
Matcher matcher = pattern.matcher(s);
int count = 0;
while (matcher.find()) {
count++;
}
System.out.println(count);
}
Обратите внимание, что StringUtils - от apache commons. Если вы не хотите включать и добавить банку, вы можете просто построить эту строку, используя цикл for.
String.join
("|",A)
. Больше нет необходимости в Apache Commons.
"\\b"
к обеим сторонам patternString
, в зависимости от точных требований.
Пытаться:
Map<String, Integer> wordCount = new HashMap<>();
for(String a : dictionnary) {
wordCount.put(a, 0);
}
for(String s : text.split("\\s+")) {
Integer count = wordCount.get(s);
if(count != null) {
wordCount.put(s, count + 1);
}
}
HashSet<String> searchWords = new HashSet<String>();
for(String a : dictionary) {
searchWords.add(a);
}
int count = 0;
for(String s : input.split("[ ,]")) {
if(searchWords.contains(s)) {
count++;
}
}
"[ ,]+"
, то есть разделить на запятую последовательность длиной один или несколько . Но ваш путь просто помещает лишние пустые строки в массив результатов, что безвредно.
int count =0;
for(int i=0;i<A.length;i++)
{
count = count + s.split(A[i],-1).length - 1;
}
Рабочий идеон: http://ideone.com/Z9K3JX
Вот что я придумал:
Он не создает никаких новых объектов. Он использует String.indexOf(String, int)
, отслеживает текущий индекс и увеличивает счетчик occount-count.
public class SearchWordCount {
public static final void main(String[] ignored) {
String[] searchWords = {"hello", "you"};
String input = "hello, hello you are so wonderful";
for(int i = 0; i < searchWords.length; i++) {
String searchWord = searchWords[i];
System.out.print(searchWord + ": ");
int foundCount = 0;
int currIdx = 0;
while(currIdx != -1) {
currIdx = input.indexOf(searchWord, currIdx);
if(currIdx != -1) {
foundCount++;
currIdx += searchWord.length();
} else {
currIdx = -1;
}
}
System.out.println(foundCount);
}
}
}
Вывод:
hello: 2
you: 1
Это полностью рабочий метод с выходом :)
public static void main(String[] args) {
String[] A={"hello", "you"};
String s= "hello, hello you are so wonderful";
int[] count = new int[A.length];
for (int i = 0; i < A.length; i++) {
count[i] = (s.length() - s.replaceAll(A[i], "").length())/A[i].length();
}
for (int i = 0; i < count.length; i++) {
System.out.println(A[i] + ": " + count[i]);
}
}
Что делает эта линия?
count[i] = (s.length() - s.replaceAll(A[i], "").length())/A[i].length();
Эта часть s.replaceAll(A[i], "")
изменяет все "привет" на пустую строку "" в тексте.
Поэтому я беру длину всего s.length()
Я вычитаю из нее длину одной и той же строки без этого слова s.replaceAll(A[i], "").length()
и я делю его на длину этого слова /A[i].length()
Пример вывода для этого примера:
hello: 2
you: 1
Вы можете использовать строковый токенизатор
Сделайте что-то вроде этого:
A = ["hello", "you"];
s = "hello, hello you are so wonderful";
StringTokenizer st = new StringTokenizer(s);
while (st.hasMoreElements()) {
for (String i: A) {
if(st.nextToken() == i){
//You can keep going from here
}
}
}