【问题标题】:Logical Error; Name Search Programming Challenge Java逻辑错误;名称搜索编程挑战 Java
【发布时间】:2018-08-06 10:24:06
【问题描述】:

我正在为我的 Intro Java 课程应对编程挑战。问题是编写一个程序,将两个最受欢迎的名字(一个“男孩”和另一个“女孩”)的 .txt 文件存储到一个 ArrayList 中,并要求用户输入一个名字,程序会告诉用户如果它是最受欢迎的。为了减轻一些混乱,我没有使用 FileReader 或 BufferedReader。

.txt 文件的格式为列表格式的“1 Jacob”。这是我的错误弹出的地方。如果我在程序中输入“Jacob”,它会告诉我它不在列表中,但如果我输入“1 Jacob”,它会说它在列表中。有没有办法省略列表中的所有整数和制表符空格?或者有没有更好的方法来应对这个编程挑战?

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors;


public class NameSearch {

public static void main(String args[]) throws IOException {

        //Open files and add to ArrayList
        Path boyNames = Paths
                .get("BoyNames.txt")
                .toAbsolutePath();

        List<String> boys = Files.lines(boyNames)
                .collect(Collectors.toList());

        Path girlNames = Paths
                .get("GirlNames.txt")
                .toAbsolutePath();

        List<String> girls = Files.lines(girlNames)
                .collect(Collectors.toList());

        //Ask user for input
        Scanner keyboard = new Scanner(System.in);

        System.out.println("Enter a Boy or Girl's name to see if it's a popular name: ");

        String name = keyboard.nextLine();

        keyboard.close();

        //Compare user input with ArrayList and print
        if (boys.contains(name) || girls.contains(name))
        {
            System.out.println(name + " is a popular name!");
        }

        else
        {
            System.out.println("Sorry, " + name + " is not a popular name.");
        }
    }
}

【问题讨论】:

  • 尝试在name object上使用sub string方法

标签: java arrays arraylist file-handling


【解决方案1】:

很简单:

List<String> boys = Files.lines(boyNames)
            .map(name -> name.replaceAll("\\d", "")) // remove numeric values
            .map(name -> name.replaceAll(" ", ""))   // remove spaces
            .collect(Collectors.toList());

 List<String> girls = Files.lines(girlNames)
                .map(name -> name.replaceAll("\\d", "")) // remove numeric values
                .map(name -> name.replaceAll(" ", ""))   // remove spaces
                .collect(Collectors.toList());

【讨论】:

  • 谢谢!我知道这很简单,但我想不通!
  • 你可以像这样一次性删除数字和空格.map(name -&gt; name.replaceAll("\\d\\s", ""))
【解决方案2】:

当您逐行读取文件时,它将按原样添加该行:例如“1 Jacob”。如果您只需要添加名称,例如“Jacob”,则需要拆分字符串。为简单起见,您可以在代码中添加以下内容:

List<String> girlNames = new ArrayList<String>();
for (String girl: girls){
    girlNames.add(girl.split(" ")[1]);
}

你可以对“男孩”做同样的事情。在比较部分,您只需要检查仅包含名称的集合:

if (boyNames.contains(name) || girlNames.contains(name))
{
    System.out.println(name + " is a popular name!");
}

【讨论】:

    【解决方案3】:

    如果认为合适,您可以通过简单地添加 map 操作来删除名称前面的前缀,如下所示:

    List<String> boys = Files.lines(boyNames)
                             .map(s -> s.substring(s.indexOf(" ") + 1))
                             .collect(Collectors.toList());
    

    其他列表也一样:

    List<String> girls = Files.lines(girlNames)
                              .map(s -> s.substring(s.indexOf(" ") + 1))
                              .collect(Collectors.toList());
    

    但是,如果您无法修改在那个时间点传入的数据,那么您可以从列表中创建一个流并执行您的 map 操作并收集到一个新列表中:

    List<String> tempBoys = boys.stream()
                                .map(s -> s.substring(s.indexOf(" ") + 1))
                                .collect(Collectors.toList());
    

    其他列表也一样:

    List<String> tempGirls = girls.stream()
                    .map(s -> s.substring(s.indexOf(" ") + 1))
                    .collect(Collectors.toList());
    

    然后将条件更改为:

    if (tempBoys.contains(name) || tempGirls.contains(name)){ ... }
    

    【讨论】: