根据条件从 java 中的字符串数组中提取单词

Extract words from an array of Strings in java based on conditions

我正在尝试做一个适用于数组和字符串的作业。代码几乎完成了,但我 运行 遇到了麻烦。每次代码 运行s,它都会替换输出数组索引中的值,而不是将新值放在不同的索引中。例如,如果我试图在字符串数组中搜索包含前缀 "b" 的单词,则预期输出为 "bat" 和 "brewers" 但相反,输出结果为 "brewers" 和 "brewers"。有什么建议么? (ps。静态主要方法用于测试目的。)

--

public static void main(String[] args) {

    String[] words = {"aardvark", "bat", "brewers", "cadmium", "wolf", "dastardly", "enigmatic", "frenetic",
            "sycophant", "rattle", "zinc", "alloy", "tunnel", "nitrate", "sample", "yellow", "mauve", "abbey",
            "thinker", "junk"};
    String prefix = "b";
    String[] output = new String[wordsStartingWith(words, prefix).length];
    output = wordsStartingWith(words, prefix);

    for (int i = 0; i < output.length; i++) {
        System.out.println("Words: " + i + " " + output[i]);
    }

}

public static String[] wordsStartingWith(String[] words, String prefix) {
    // method that finds and returns all strings that start with the prefix

    String[] returnWords;
    int countWords = 0;

    for (int i = 0; i < words.length; i++) {
        // loop to count the number of words that actually have the prefix
        if (words[i].substring(0, prefix.length()).equalsIgnoreCase(prefix)) {
            countWords++;
        }
    }

    // assign length of array based on number of words containing prefix
    returnWords = new String[countWords];

    for (int i = 0; i < words.length; i++) {
        // loop to put strings containing prefix into new array
        for (int j = 0; j < returnWords.length; j++) {
            if (words[i].substring(0, prefix.length()).equalsIgnoreCase(prefix)) {
                returnWords[j] = words[i];
            }
        }
    }

    return returnWords;
}

--

谢谢

灵魂

是因为你写的代码。如果你考虑得当,你就会意识到你的错误。

罪魁祸首代码

for (int j = 0; j < returnWords.length; j++) {
    if (words[i].substring(0, prefix.length()).equalsIgnoreCase(prefix)) {
        returnWords[j] = words[i];
    }
}

当你得到一个匹配的词时,你将整个输出数组设置为该词。这意味着找到的最后一个满足条件的单词将替换数组中所有先前的单词。

数组 returnWords 的所有元素首先初始化为 "bat",然后每个元素被替换为 "brewers"

修改后的代码是这样的

int j = 0;
for (int i = 0; i < words.length; i++) {
    if (words[i].substring(0, prefix.length()).equalsIgnoreCase(prefix)) {
        returnWords[j] = words[i];
        j++;
    }
}

此外,您正在进行多次迭代,这并不是完全需要的。

比如这个语句

String[] output = new String[wordsStartingWith(words, prefix).length];
output = wordsStartingWith(words, prefix);

可以更正为更简单的语句 String[] output = wordsStartingWith(words, prefix);

您这样做的方式是多次循环遍历同一个数组。 您只需检查一次值:

public static void main(String[] args) {
    String[] words = {"aardvark", "bat", "brewers", "cadmium", "wolf", "dastardly", "enigmatic", "frenetic",
            "sycophant", "rattle", "zinc", "alloy", "tunnel", "nitrate", "sample", "yellow", "mauve", "abbey",
            "thinker", "junk"};
    String prefix = "b";

    for (int i = 0; i < words.length; i++) {
        if (words[i].toLowerCase().startsWith(prefix.toLowerCase())) {
            System.out.println("Words: " + i + " " + words[i]);
        }
    }
}

与其做两个单独的循环,不如尝试只做一个:

String[] returnWords;
int[] foundWords = new int[words.length];
int countWords = 0;

for (int i = 0; i < words.length; i++) {
    // loop to count the number of words that actually have the prefix
    if (words[i].substring(0, prefix.length()).equalsIgnoreCase(prefix)) {
        foundWords[index] = words[i];
        countWords++;
    }
}

// assign length of array based on number of words containing prefix
returnWords = new String[countWords];
for (int i = 0; i < countWords; i++) {
    returnWords[i] = foundWords[i];
}

我的方法有另一个数组 (foundWords),用于存放您在第一个循环中找到的所有单词,其大小为 words,以防每个单词都以前缀开头。 index 跟踪找到的单词在 foundWords 中的位置。最后,您只需要遍历 countWords 并将每个元素分配给您的 returnWords.

这不仅会修复您的代码,还会对其进行优化,使其 运行 更快(非常轻微;词库越大,搜索速度越快)。

不要重新发明轮子。您的代码可以替换为这个单一的、易于阅读、无错误的行:

String[] output = Arrays.stream(words)
    .filter(w -> w.startsWith(prefix))
    .toArray(String[]::new);

或者如果您只想打印匹配的词:

Arrays.stream(words)
    .filter(w -> w.startsWith(prefix))
    .forEach(System.out::println);