2013-02-25 2 views
-2

Метод ниже выполняет эту работу, но это не очень эффективно.Обнаружить, если две строки содержат только одинаковые слова.

Кто-нибудь знает более элегантное решение для этого?

я возился с чем-то вроде этого, но не везло до сих пор:/^ (Foo | Бар | [[: пространство:] [пунктуатором]]) + $/

static public boolean matchTitle(String title, String title2) { 

    Scanner scanner1 = new Scanner(title); 
    Scanner scanner2 = new Scanner(title2); 
    String searchTitle = title2; 
    boolean match = false; 
    int i = 0; 
    while(i < 2){ 
     if(i == 1){ 
      scanner1 = new Scanner(title2); 
      scanner2 = new Scanner(title); 
      searchTitle = title; 
     } 

     // breaks into words 
     while (scanner1.hasNext()){ 
      match = false; 

      String token = scanner1.next(); 
      scanner2 = new Scanner(searchTitle); 
      while (scanner2.hasNext() && !match){ 
       String token2 = scanner2.next(); 
       if(token.equals(token2)){ 
        // if the words match 
        match = true; 
       } 
      } 
      if(!match){ // we have a word that didn't match any words in the second title 
       return false; 
      } 
     } 
     i++; 
    } 
    return true; 
} 

Пример

("аналогичные слова здесь", "подобные слова здесь") // истинные

("аналогичные слова здесь", "слова здесь подобные здесь") // истинные

("подобные слова он повторно», "подобные слова здесь разные") // ложные

+3

Пожалуйста, введите пример ввода, который вы ожидаете для каждого случая (true/false). –

+0

Пример: («похожие слова здесь», «похожие слова здесь») // true («похожие слова здесь», «здесь похожие слова») // true («похожие слова здесь», «похожие слова здесь разные») // false –

+1

Вы можете использовать regex для достижения этого? – pcalcao

ответ

3

Я хотел бы пойти на более простую версию:

List<String> words1 = Arrays.asList(title.split(" ")); 
List<String> words2 = Arrays.asList(title2.split(" ")); 

return words1.containsAll(words2) && 
     words2.containsAll(words1); 

допущениях:

  • названия и title2 являются не нулевым
  • пространства является единственным разделителем
  • если строка содержит одно и то же слово n раз, другое должно содержать это слово n раз слишком

EDIT

Ваша правка показывает, что дублирует все в порядке. В этом случае вы можете использовать набор вместо списка:

Set<String> words1 = new HashSet<String> (Arrays.asList(title.split(" "))); 
Set<String> words2 = new HashSet<String> (Arrays.asList(title2.split(" "))); 

return words1.size() == words2.size() && words1.containsAll(words2); 

Примечание: как указано chm052 in his answer, в случае наборов, вы можете просто проверить равенство, которое не учитывает порядок (но не в списке пример):

return words1.equals(words2); 
+0

«если строка содержит одно и то же слово дважды, другое должно содержать это слово дважды» - это правда? Или просто нужно иметь/один/из слов дважды (так что такая же длина)? На самом деле, это ложно выводит true для («один два три», «один два два»)? – chm

+0

@ chm052 обе версии выводят false. – assylias

+0

Мой первый пост, ха-ха, вы, ребята, на нем и грубо. Все нормально, я новичок в SOF. Благодаря многопользовательской аське, это решение отлично работает, и я заметил как минимум 10-кратное увеличение в моем приложении, заменив мой метод на это. –

1

Что вы спрашиваете, кастрированный баран на набора слов в первой строке равно набора слов во второй строке. В конце концов, вещи, которые вы хотите игнорировать о строке (порядок слов и повторяющиеся слова), по определению не существуют в наборах.

Итак, вам нужно

Set<String> words1 = new HashSet<String> (Arrays.asList(title.split(" "))); 
Set<String> words2 = new HashSet<String> (Arrays.asList(title2.split(" "))); 

return words1.equals(words2); 

EDIT:

Как assylias отметил, что нет большого изменения в функциональности, если вы переключитесь использовать метод Equals, а не размер и методы containsAll, но это легче для понимания при чтении кода. Также, вероятно, лучше использовать OO для развязывания этого метода с заданным классом; то, например, если в наборе классов Java реализован лучший алгоритм для поиска равенства глубоких множеств, вы сможете использовать это улучшение.

БОНУС ВТОРОЙ EDIT:

Если кто-то смущает комментарию нить на это, он об этом предыдущем ответе по assylias (и Wether или не будет работать в любом случае):

List<String> words1 = Arrays.asList(title.split(" ")); 
List<String> words2 = Arrays.asList(title2.split(" ")); 
return words1.size() == words2.size() && words1.containsAll(words2); 
+0

Как уже отмечалось выше, версия списка выводит false в 'matchTitle (« один два два »,« один два три »));' - В частности, 'words1.containsAll (words2)' будет false. – assylias

+0

Но согласился с вашим вторым кодом, в случае с List, containsAll необходимо было игнорировать порядок слов, но в случае Set, 'equals' является агностиком заказа. – assylias

+0

@ chm052 Спасибо за это редактирование, это работает. Я не знаю, я полагаю, чтобы изменить ответ на этот вопрос, я даже не могу стрелять, чтобы щелкнуть по нему, потому что это новая учетная запись. Хех, я хорошо знаю, что все это работает –

Смежные вопросы