0

So I have a problem that takes the names of people from a user and stores them in an ArrayList(personalNames). After that I need to take that list and remove any name that has anything besides letters a-z (anything with numbers or symbols) in it and put them into a separate ArrayList(errorProneNames) that holds the errors. Could someone help me with the removal part?

public class NameList {

public static void main(String[] args) {

    ArrayList<String> personalNames = new ArrayList<String>();
    Scanner input = new Scanner(System.in);
    String answer;

    do{
    System.out.println("Enter the personal Names: ");
    String names = input.next();

    personalNames.add(names);
    System.out.println("would you like to enter another name (yes/no)?");
    answer = input.next();
     } while (answer.equalsIgnoreCase("yes"));



    ArrayList<String> errorProneNames = new ArrayList<String>();


}

}

7 Answers 7

2

If it's the "how do I remove an element from an ArrayList<>" part which is causing problems, and you want to check all the values, you probably want to use an Iterator and call remove on that:

for (Iterator<String> iterator = personalNames.iterator(); iterator.hasNext(); ) {
    String name = iterator.next();
    if (isErrorProne(name)) {
        iterator.remove();
    }
}

Note that you mustn't remove an element from a collection while you're iterating over it in an enhanced-for loop except with the iterator. So this would be wrong:

// BAD CODE: DO NOT USE
for (String name : personalNames) {
    if (isErrorProne(name)) {
        personalNames.remove(name);
    }
}

That will throw a ConcurrentModificationException.

Another option would be to create a new list of good names:

List<String> goodNames = new ArrayList<>();
for (String name : personalNames) {
    if (!isErrorProne(name)) {
        goodNames.add(name);
    }
}

Now, if your real problem is that you don't know how to write the isErrorProne method, that's a different matter. I suspect that you want to use a regular expression to check that the name only contains letters, spaces, hyphens, and perhaps apostrophes - but you should think carefully about exactly what you want here. So you might want:

private static boolean isErrorProne(String name) {
    return !name.matches("^[a-zA-Z \\-']+$");
}

Note that that won't cope with accented characters, for example. Maybe that's okay for your situation - maybe it's not. You need to consider exactly what you want to allow, and adjust the regular expression accordingly.

You may also want to consider expressing it in terms of whether something is a good name rather than whether it's a bad name - particularly if you use the last approach of building up a new list of good names.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you a ton! the part ("^[a-zA-Z \\-']+$"); was where i had no clue at all.
@Joey: In future, it's worth trying to isolate your question to make it just about the part you need help with. If you were already comfortable with the removal part, it would have been better to write the question just in terms of "How can I validate that a string only contains the characters I want?"
1

Here is your solution :

String regex = "[a-zA-Z]*";
for (String temp : personalNames ) {
    if (!temp.matches(regex)){
        errorProneNames.add(temp);
        personalNames.remove(temp);
    }
}

Comments

1

You can use the remove() method of ArrayList

personalNames.remove("stringToBeRemoved");

Lot of overloaded methods are available. You can delete with index, Object(String itself) etc. You can see Javadocs for more info.

Also to remove all String having anything but a-z letters you can use regex. Logic is as follows

    String regex = "[a-zA-Z]*";
    String testString = "abc1";
    if(!testString.matches(regex)){
        System.out.println("Remove this");
    }

As Jon pointed out while iterating over the List do not use the Lists's remove() method but the iterators remove() method.

6 Comments

You not answered the Ops Question.
Yes. But i do not know how to remove all string inputs that have numbers/symbols in them
Note that if you do this while iterating over the collection, it will throw an exception.
Yes in that case you need to use iterator.remove() or else you will get concurrentModificationExeption.
Indeed. And given that the OP wants to check all the names, it seems unlikely that the method you've shown will actually be useful, IMO.
|
0

There are two ways you can do this:

The first is to iterate backwards through the list, remove them, then add them into the second list. I say to do it backwards, because it will change the index.

for (int i = personalNames.size()-1; i >=0; i++) {
   if (isBadName(personalNames.get(i)]){
      errorProneNames.add(personalNames.get(i));
      personalNames.remove(i);  
   }
}

The second way is to use the Iterator provided by ArrayList (personalNames.iterator()). This will allow you to go forward.

Comments

0

I would probably do this

// Check that the string contains only letters.
private static boolean onlyLetters(String in) {
  if (in == null) {
    return false;
  }
  for (char c : in.toCharArray()) {
    if (!Character.isLetter(c)) {
      return false;
    }
  }
  return true;
}

public static void main(String[] args) {
  ArrayList<String> personalNames = new ArrayList<String>();
  ArrayList<String> errorProneNames = new ArrayList<String>(); // keep this list here.
  Scanner input = new Scanner(System.in);
  String answer;
  do {
    System.out.println("Enter the personal Names: ");
    String names = input.next();
    if (onlyLetters(names)) { // test on input.
      personalNames.add(names); // good.
    } else {
      errorProneNames.add(names); // bad.
    }
    System.out
        .println("would you like to enter another name (yes/no)?");
    answer = input.next();
  } while (answer.equalsIgnoreCase("yes"));
}

Comments

0

get an iterator from list, while itr has next element give it to a method for example isNotProneName which takes a String and returns true or false, if the given String matches not your needs. if false returned remove string from itr and add it to the other list

Comments

0

Use regex [a-zA-Z ]+ with String.matches to test error-prone name and Iterator to remove.

    Iterator<String> it=personalNames.iterator();
    while(it.hasNext()){
        String name=it.next();
        if(name.matches("[a-zA-Z ]+")){
          it.remove();
        }
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.