【问题标题】:How to remove a range of string objects from an arraylist based on first initials inputted by the user?如何根据用户输入的首字母缩写从数组列表中删除一系列字符串对象?
【发布时间】:2019-07-27 12:46:30
【问题描述】:

所以我有一个项目,我需要创建一个包含所有 50 个州的数组列表。然后我必须允许用户输入两个不同的字母。然后我必须删除所有以这些字母开头的状态以及介于两者之间的所有状态。例如。如果有人输入了“D-I”,所有以 D-I 开头的状态都应该被删除。

到目前为止,我已经提出了这个程序,但是当我运行它时,它不仅会删除我输入的字母范围内的所有状态,而且还会删除第一个字母之前的所有状态。例如。如果我输入“D-I”,所有以 A-I 开头的状态都将被删除,而应该是所有以 D-I 开头的状态。

有人可以帮我解决这个问题吗?

import java.util.ArrayList;
import java.util.Scanner;

public class States {
    public static void main(String[] args) {
        String removeStates;
        String firstInitial;
        String secondInitial;
        String stateInitial;
        int first = 0;
        int last = 0;
        
        Scanner input = new Scanner(System.in);
        ArrayList<String> states = new ArrayList<>();
        
        states.add("Alabama");
        states.add("Alaska");
        states.add("Arizona");
        states.add("Arkansas");
        states.add("California");
        states.add("Colorado");
        states.add("Connecticut");
        states.add("Delaware");
        states.add("District of Columbia");
        states.add("Florida");
        states.add("Georgia");
        states.add("Hawaii");
        states.add("Idaho");
        states.add("Illinois");
        states.add("Indiana");
        states.add("Iowa");
        states.add("Kansas");
        states.add("Kentucky");
        states.add("Louisiana");
        states.add("Maine");
        states.add("Maryland");
        states.add("Massachusetts");
        states.add("Michigan");
        states.add("Minnesota");
        states.add("Mississippi");
        states.add("Missouri");
        states.add("Montana");
        states.add("Nebraska");
        states.add("Nevada");
        states.add("New Hampshire");
        states.add("New Jersey");
        states.add("New Mexico");
        states.add("New York");
        states.add("North Carolina");
        states.add("North Dakota");
        states.add("Ohio");
        states.add("Oklahoma");
        states.add("Oregon");
        states.add("Pennsylvania");
        states.add("Rhode Island");
        states.add("South Carolina");
        states.add("South Dakota");
        states.add("Tennessee");
        states.add("Texas");
        states.add("Utah");
        states.add("Vermont");
        states.add("Virginia");
        states.add("Washington");
        states.add("West Virginia");
        states.add("Wisconsin");
        states.add("Wyoming");
        
        System.out.println(states.toString());
        
        System.out.print("Enter the range of the states you would like to remove based on the first initials (e.g. A-D [not case sensitive]): ");
        
        removeStates = input.nextLine();
        
        firstInitial = removeStates.substring(0, 1);
        
        secondInitial = removeStates.substring(2);
        
        for (int i = 0; i < states.size(); i++) {
            stateInitial = states.get(i).substring(0, 1);
            
            if (stateInitial.equalsIgnoreCase(firstInitial) || stateInitial.equalsIgnoreCase(secondInitial)) {
            
                for (int j = i+1; j>0; j--){
                    states.remove(i);
                    i--;
                }
            }
        }
        System.out.println(states.toString());

    }
}

这是我的输出现在的样子。底部/第三行是问题所在。如您所见,当我输入“G-K”时(顺便说一句,这不区分大小写),它删除了所有以 A-K 开头的状态,而不是那些以 G-K 开头的状态

[Alabama, Alaska, Arizona, Arkansas, California, Colorado, Connecticut, Delaware, District of Columbia, Florida, Georgia, Hawaii, Idaho, Illinois, Indiana, Iowa, Kansas, Kentucky, Louisiana, Maine, Maryland, Massachusetts, Michigan, Minnesota, Mississippi, Missouri, Montana, Nebraska, Nevada, New Hampshire, New Jersey, New Mexico, New York, North Carolina, North Dakota, Ohio, Oklahoma, Oregon, Pennsylvania, Rhode Island, South Carolina, South Dakota, Tennessee, Texas, Utah, Vermont, Virginia, Washington, West Virginia, Wisconsin, Wyoming]
Enter the range of the states you would like to remove based on the first initials (e.g. A-D [not case sensitive]): g-k
[Louisiana, Maine, Maryland, Massachusetts, Michigan, Minnesota, Mississippi, Missouri, Montana, Nebraska, Nevada, New Hampshire, New Jersey, New Mexico, New York, North Carolina, North Dakota, Ohio, Oklahoma, Oregon, Pennsylvania, Rhode Island, South Carolina, South Dakota, Tennessee, Texas, Utah, Vermont, Virginia, Washington, West Virginia, Wisconsin, Wyoming]

【问题讨论】:

  • String#startsWith?

标签: java string object arraylist


【解决方案1】:

这里不是故意的,但确实如此,你写的:

for (int j = i+1; j>0; j--){
                states.remove(i);
                i--;
            }

假设您的第一个字母是“C”,那么您作为外循环进入内循环的第一个索引将是 i == 4(加利福尼亚州)。然后,您使用 j = i+1 = 5 的起始值调用内部循环,并逐渐向下移动数组索引。所以你删除 5(顺便说一句,从 1 到高),然后是 4,然后是 3,然后是 2,依此类推。因此,一旦找到第一个条目,您就删除了指向它的所有条目。

【讨论】:

  • 顺便说一句:从字符串中获取单个字符而不是子字符串的更好方法是 s.charAt(index) :)
【解决方案2】:

这是一种使用流删除不需要的状态的替代方法:

char firstInitial = removeStates.charAt(0);
char secondInitial = removeStates.charAt(2);

Collection<String> statesToRemove = states.stream()
       .filter(state -> state.charAt(0) >= firstInitial)
       .filter(state -> state.charAt(0) <= secondInitial)
       .collect(Collectors.toList());

states.removeAll(statesToRemove);

您也可以只调整过滤器以仅过滤剩余状态以使其更简单。

【讨论】:

  • 但请记住性能(代码复杂性): - 流隐式循环遍历所有元素 - removeAll 方法再次循环遍历所有列表元素。因此,在这种情况下,您将获得 2N 的代码复杂度。使用 removeIf 实现(@Kartik 提到的基于 lambda 的方法,以及我提供的没有 lambda 但使用 Predicate 实现的答案)允许只通过一个循环遍历所有元素来删除不需要的项目,因此复杂度为 N。
  • 是的,我试图坚持现有的逻辑,但 removeIf 绝对是最好的选择。
【解决方案3】:

这可以使用removeIf()在单个语句中完成:

states.removeIf(s -> s.charAt(0) >= 'D' && s.charAt(0) <= 'I');

您可以将'D' 替换为removeStates.charAt(0),将'I' 替换为removeStates.charAt(2)

【讨论】:

  • 试过了。未从列表中删除任何内容。
  • @AmericanIdiot 您正在输入小写字母。输入大写字母,或使用removeStates,如removeStates.toUpperCase().charAt(0)
【解决方案4】:

您可以简单地使用事实来代替循环,即

  • 列表已排序
  • 字符串的比较器按字典顺序比较,所以顺序是 A、Aa、Aaa、Aab、Abb、Baa、...
  • List 接口实现了一个“removeIf”方法,允许您根据您实现的规则测试字符串

因此,您可以简单地编写代码,而不是 for 循环:

    firstInitial = removeStates.substring(0, 1);

    secondInitial = removeStates.substring(2);

    states.removeIf(new Predicate<String>() {

        @Override
        public boolean test(String t) {
            boolean isBeforeFirstInitial = (firstInitial.compareTo(t) >=0);
            boolean isAfterLastInitial = (secondInitial.compareTo(t) <=0);
            boolean startsWithLastInitial = t.startsWith(secondInitial);

            return !(isBeforeFirstInitial||isAfterLastInitial)||startsWithLastInitial;
        }
    });

不要忘记将首字母转换为大写(您的文字说明输入不区分大小写)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-11-14
    • 1970-01-01
    • 1970-01-01
    • 2022-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-17
    相关资源
    最近更新 更多