遍历两个数组列表的问题

Issue iterating through two arraylists

编辑:非常感谢所有非常快速的反馈。哇。我只是为您粘贴了所有内容,而不仅仅是那两个 for 循环。谢谢

这可能之前已经完全回答过了。过去几年我读过 SO,但这是我的第一本 post。我一直在使用该网站和其他网站来帮助解决这个问题,所以如果有人回答这个问题,我提前表示歉意!

我正在遍历两个数组列表。一个来自用户输入;另一个是转换成数组列表的字典文件。我正在尝试将输入中的单词与字典中的单词进行比较。输入列表和字典列表是有效的,如果我简单地遍历它们,它们包含它们应该包含的内容(所以这不是问题。我认为我的问题在于我如何处理迭代。我是一个相当新手 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;
}

输入的输出结果"test tester asdasdfasdlfk" [测试, 测试不匹配, 测试, 测试不匹配]

您应该将字典放入 HashSet 并 trim 添加所有单词。接下来你只需要循环输入列表并与 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();

trim 应该在将元素添加到列表时进行。 Trim 每次的字典值都是开销。内部循环本身也是如此。如果将字典数据结构从List改为Set,可以降低任务的复杂度。

将"fail"的结果移到外层循环的末尾。否则最后输入字符串的结果不会添加到结果列表中。

下面的代码很糟糕:

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

检查器不会在字典循环内更改。但是每次检查器和字典值不匹配时都会构造失败字符串。

看起来输入中的每个词都与字典中的每个词进行了比较。因此,对于每个不匹配的单词,您都会失败(尽管您只将字典中的最后一个失败写入结果)。问题似乎是即使在找到该词后您仍会继续循环。为避免这种情况,您可能希望将 break 添加到成功案例中:

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

Carl Manaster 给出了正确的解释。

这是您的代码的改进版本:

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 来存储字典和 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;
                }

我认为您的代码或多或少应该像下面这样。

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();