2015-07-21 1 views
0

EDIT: Большое спасибо за все очень быструю обратную связь. Вау. Я просто вложил все это для вас, а не только для двух циклов. Благодарю.Проблема, повторяющаяся через двух архаистов

Это, возможно, было полностью отвечено раньше. Я прочитал SO за последние несколько лет, но это мой первый пост. Я использовал сайт и другие, чтобы помочь решить эту проблему, поэтому приносим извинения заранее, если на это был дан ответ!

Я повторяю через два arraylists. Один из них получен из пользовательского ввода; другой - файл словаря, преобразованный в arraylist. Я пытаюсь сравнить слово во входном слове со словарем. Список ввода и список словарей действительны, и если я просто перебираю их, они содержат то, что им нужно (так что это не проблема. Я предполагаю, что моя проблема где-то с тем, как я обрабатываю итерацию. начинающий Java программист так пожалуйста легко идти на меня.

Благодаря

public String isSub(String x) throws FileNotFoundException, IOException { 
    //todo handle X 
    String out = "**********\nFor input \n" + x + "If you're reading this no match was found.\n**********"; 
    String dictionary; 


    boolean solve = true; 

    /// Get dictionary 
    dictMaker newDict = new dictMaker(); 
    dictionary = newDict.arrayMaker(); 

    List<String> myDict = new ArrayList<String>(Arrays.asList(dictionary.split(","))); 
    List<String> input = new ArrayList<String>(Arrays.asList(x.split(" "))); 
    List<String> results = new ArrayList<String>(); 
    //results = input; 

    String currentWord; 
    String match = ""; 
    String checker = ""; 
    String fail=""; 


    //Everything to break sub needs to happen here. 
    while (solve) { 


    for(int n = 0; n < input.size(); n++) { //outside FOR (INPUT) 
     if(!fail.equals("")) results.add(fail); 
     checker = input.get(n).trim(); 
     for(int i = 0; i < myDict.size(); i++) { //inside FOR (dictionary) 
     currentWord = myDict.get(i).trim(); 
     System.out.print(checker + " " + currentWord + "\n"); 
     if(checker.equals(currentWord)) { 

       match = currentWord; 
       results.add(currentWord); 
       fail=""; 

      } //end if 
      else { 

       fail = "No match for " + checker; 

      } 

      }//end inside FOR (dictionary) 

     } //END OUTSIDE FOR (input) 

     solve=false; 

    } //end while 


     out = results.toString(); 

     return out; 
} 

Вывод результатов для ввода «тест тестер asdasdfasdlfk» [тест, не подходят для тестирования, тестер, не подходит для тестера]

+0

Ваш код, кажется, ожидает список строк, и ваш пример, кажется, проходит в одной строке с пробелами для разделения. Если это то, что вы делаете, результаты верны, как ожидалось, и передача ввода «тест» или «тестер» будет соответствовать одному из двух. Кроме того, у вас есть код отладки - полный вывод программы поможет кучу, чтобы добраться до сути. – Cobusve

+0

Глядя на то, как вы повторяетесь, я думаю, что вы пытаетесь сделать checker.startsWith (currentWord) вместо равных ... – Cobusve

+0

Превосходное количество быстрых и точных и полезных ответов. Всем спасибо! –

ответ

1

Карл Дэвид Мэнэстер дал правильное объяснение.

Вот улучшенная версия кода:

for (int n = 0; n < input.size(); n++) { //outside FOR (INPUT) 
    String checker = input.get(n).trim(); 
    boolean match = false; 
    for (int i = 0; i < myDict.size(); i++) { //inside FOR (dictionary) 
     String currentWord = myDict.get(i).trim(); 
     System.out.print(checker + " " + currentWord + "\n"); 
     if (checker.equals(currentWord)) { 
      match = true; 
      results.add(currentWord); 
      break; 
     } //end if 
    } //end inside FOR (dictionary) 
    if (!match) { 
     results.add("No match for " + checker); 
    } 
} //END OUTSIDE FOR (input) 

Кроме того, рекомендуется использовать HashMap вместо ArrayList хранить словарь и обрезать слова, когда вы храните их, чтобы избежать делать это в каждом проходе.

+0

Это действительно сработало отлично. –

-1

Вы должны поместить словарь в HashSet и обрезать, добавив все слова. Затем вам нужно всего лишь скопировать список входных данных и сравнить с dict.conatins(inputWord). Это сохраняет возможный огромный цикл словаря, обработанный для всех входных слов.

Непроверено свалка мозга:

HashSet<String> dictionary = readDictionaryFiles(...); 
List<String> input = getInput(); 

for (String inputString : input) 
{ 
    if (dictionary.contains(inputString.trim())) 
    { 
      result.add(inputString); 
    } 
} 

out = result.toString() 
.... 

И решение похоже на оригинальное сообщение. Изменяются ненужные переменные индекса цикла:

for (String checker : input) 
    { // outside FOR (INPUT) 
     fail = "No match for " + checker; 
     for (String currentWord : myDict) 
     { // inside FOR (dictionary) 
      System.out.print(checker + " " + currentWord + "\n"); 
      if (checker.equals(currentWord)) 
      { 
       match = currentWord; 
       results.add(currentWord); 
       fail = null; 
       break; 
      } 
     } // end inside FOR (dictionary) 
     if (fail != null) 
     { 
      results.add(fail); 
     } 
    } // end outside FOR (input) 

    solve = false; 

    return results.toString(); 

Обложка должна быть сделана при добавлении элементов в список. Обрезать словарные значения каждый раз накладные расходы. И внутренняя петля тоже. Сложность задачи может быть уменьшена, если структура данных словаря будет изменена с List на Set.

Добавление результата «fail» перемещается в конец внешнего контура. В противном случае результат последней строки ввода не будет добавлен в список результатов.

Следующий код ужасен:

else { 
    fail = "No match for " + checker; 
} 

Средство проверки не изменяется в пределах цикла словаря. Но строка сбоя создается каждый раз, когда контрольная сумма и значение словаря не совпадают.

+0

Хороший вопрос об этой части кода, Конрад. Спасибо что подметил это. –

1

Похоже, что каждое слово во входных данных сравнивается с каждым словом в вашем словаре. Поэтому для каждого слова, которое не соответствует, вы получаете сбой (хотя вы только записываете последний сбой в словаре для результатов). Проблема заключается в том, что вы продолжаете цикл даже после того, как нашли слово. Чтобы избежать этого, вы, вероятно, хотите добавить break в случае успеха:

if (checker.equals(currentWord)) { 
    match = currentWord; 
    results.add(currentWord); 
    fail = ""; 
    break; 
} else { 
    fail = "No match for " + checker; 
} 
+0

Верно, я вижу вашу точку зрения. Но если он разрывает этот цикл, он просто разрывает внутреннюю часть цикла и продолжит цикл while, или он тоже сломает цикл while и заканчивается? Снова, извините за мою новизну ;-) –

+0

Построение отказа ветви else может быть перемещено до цикла словаря, поскольку 'checker' не изменяется в цикле. – Konrad

+0

@TomV Просто попробуйте и посмотрите ... – csmckelvey

0

Если вы используете словарь, вы должны получить его с ключами не с индексом. Таким образом, это должно быть

   if(myDict.containsKey(checker)){ 
        String currentWord =myDict.get(checker); 
        System.out.print(checker + " " + currentWord + "\n"); 
        match = currentWord; 
        results.add(currentWord); 
        fail = ""; 
       } 
       else { 
        fail = "No match for " + checker; 
       } 

Я думаю, что более или менее ваш код должен понравиться следующим.

ArrayList<String> input= new ArrayList<String>(); 
     input.add("ahmet"); 
     input.add("mehmet"); 
     ArrayList<String> results= new ArrayList<String>(); 
     Map<String, String> myDict = new HashMap<String, String>(); 
     myDict.put("key", "ahmet"); 
     myDict.put("key2", "mehmet"); 
     String match=""; 
     String fail=""; 
    for (int n = 0; n < input.size(); n++) { //outside FOR (INPUT) 
      if (!fail.equals("")) 
       results.add(fail); 
      String checker = input.get(n).trim(); 

      for (int i = 0; i < myDict.size(); i++) { //inside FOR (dictionary) 

      // String currentWord = myDict.get(i).trim(); 
       if(myDict.containsKey(checker)){ 
        String currentWord =myDict.get(checker); 
        System.out.print(checker + " " + currentWord + "\n"); 
        match = currentWord; 
        results.add(currentWord); 
        fail = ""; 
       } 
       else { 
        fail = "No match for " + checker; 
       } 
      } // end inside FOR (dictionary) 
     } // end outside FOR (input) 

    // solve = false; I dont know what is this 

    //} //end while. no while in my code 

    return results.toString(); 
+0

Зачем использовать карту для хранения словаря? И почему сравнивать ключ в myDict, а не значение? Примеры клавиш «ключ» и «ключ2» никогда не соответствуют значению от ввода. – Konrad

+0

Честно говоря, я не очень хорошо проверил код, я просто хочу дать представление о том, как сравнивать и извлекать из словаря. Для получения дополнительной информации, почему это карта, словарь. http://docs.oracle.com/javase/7/docs/api/java/util/Dictionary.html http://stackoverflow.com/questions/13543457/how-do-you-create-a-dictionary-in -java http://www.tutorialspoint.com/java/java_dictionary_class.htm – Memin

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