我正在尝试检查字符串是否包含字母表中的所有字母。我创建了一个ArrayList
,其中包含整个字母表。我将字符串转换为char数组,并且我遍历字符数组,并且对于ArrayList
中存在的每个字符,我从中删除了一个元素。最后,我尝试检查Arraylist
是否为空,以查看是否已删除所有元素。这表明字符串包含字母表中的所有字母。
不幸的是,代码在if条件中抛出了IndexOutOfBoundsException
错误,我从arraylist中移除了元素
List<Character> alphabets = new ArrayList<Character>();
alphabets.add('a');
alphabets.add('b');
alphabets.add('c');
alphabets.add('d');
alphabets.add('e');
alphabets.add('f');
alphabets.add('g');
alphabets.add('h');
alphabets.add('i');
alphabets.add('j');
alphabets.add('k');
alphabets.add('l');
alphabets.add('m');
alphabets.add('n');
alphabets.add('o');
alphabets.add('p');
alphabets.add('q');
alphabets.add('r');
alphabets.add('s');
alphabets.add('t');
alphabets.add('u');
alphabets.add('v');
alphabets.add('w');
alphabets.add('x');
alphabets.add('y');
alphabets.add('z');
// This is the string- I've just put a random example
String str = "a dog is running crazily on the ground who doesn't care about the world";
//Remove all the spaces
str = str.replace(" ", "");
// Convert the string to character array
char[] strChar = str.toCharArray();
for (int i = 0; i < strChar.length; i++) {
char inp = strChar[i];
if (alphabets.contains(inp)) {
alphabets.remove(inp);
}
}
if (alphabets.isEmpty())
System.out.println("String contains all alphabets");
else
System.out.println("String DOESN'T contains all alphabets");
答案 0 :(得分:77)
All these solutions seem to do a lot of work for a relatively simple check, especially given Java 8's stream API:
/* Your lowercase string */.chars()
.filter(i -> i >= 'a' && i <= 'z').distinct().count() == 26;
Edit: For speed
If you want to end the string iteration as soon as the entire alphabet is found, then you can keep track with a HashSet
internally:
Set<Integer> chars = new HashSet<>();
String s = /* Your lowercase string */;
s.length > 25 && s.chars()
.filter(i -> i >= 'a' && i <= 'z') //only alphabet
.filter(chars::add) //add to our tracking set if we reach this point
.filter(i -> chars.size() == 26) //filter the 26th letter found
.findAny().isPresent(); //if the 26th is found, return
This way, the stream will cease as soon as the Set
is filled with the 26 required characters.
There are some (even still) more efficient solutions in terms of performance below, but as a personal note I will say to not bog yourself in premature optimization too much, where you could have readability and less effort in writing the actual code.
答案 1 :(得分:16)
List.remove
removes by index. Since a char
can be cast to an int you are effectively removing index values that do not exist, ie char 'a' is equal to int 97. As you can see your list does not have 97 entries.
You can do alphabet.remove(alphabets.indexOf(inp))
;
As pointed out by @Scary Wombat(https://stackoverflow.com/a/39263836/1226744) and @Kevin Esche (https://stackoverflow.com/a/39263917/1226744), there are better alternative to your algorithm
答案 2 :(得分:9)
Regex is your friend. No need to use a List
here.
public static void main(String[] args) {
String s = "a dog is running crazily on the ground who doesn't care about the world";
s = s.replaceAll("[^a-zA-Z]", ""); // replace everything that is not between A-Za-z
s = s.toLowerCase();
s = s.replaceAll("(.)(?=.*\\1)", ""); // replace duplicate characters.
System.out.println(s);
System.out.println(s.length()); // 18 : So, Nope
s = "a dog is running crazily on the ground who doesn't care about the world qwertyuioplkjhgfdsazxcvbnm";
s = s.replaceAll("[^a-zA-Z]", "");
s = s.toLowerCase();
s = s.replaceAll("(.)(?=.*\\1)", "");
System.out.println(s);
System.out.println(s.length()); //26 (check last part added to String) So, Yes
}
答案 3 :(得分:9)
O(n)解决方案
static Set<Integer> alphabet = new HashSet<>(26);
public static void main(String[] args) {
int cnt = 0;
String str = "a dog is running crazily on the ground who doesn't care about the world";
for (char c : str.toCharArray()) {
int n = c - 'a';
if (n >= 0 && n < 26) {
if (alphabet.add(n)) {
cnt += 1;
if (cnt == 26) {
System.out.println("found all letters");
break;
}
}
}
}
}
答案 4 :(得分:8)
Adding to @Leon answer, creating a List
and removing from it seems quite unnecessary. You could simply loop over 'a' - 'z'
and do a check with each char
. Additionally you are looping over the whole String
to find out, if each letter is present. But the better version would be to loop over each letter itself. This can potentionally safe you a few iterations.
In the end a simple example could look like this:
// This is the string- I've just put a random example
String str = "a dog is running crazily on the ground who doesn't care about the world";
str = str.toLowerCase();
boolean success = true;
for(char c = 'a';c <= 'z'; ++c) {
if(!str.contains(String.valueOf(c))) {
success = false;
break;
}
}
if (success)
System.out.println("String contains all alphabets");
else
System.out.println("String DOESN'T contains all alphabets");
答案 5 :(得分:5)
Another answer has already pointed out the reason for exception. You have misused List.remove()
, as it implicitly convert char
to int
which it called the List.remove(int)
which remove by index.
The way to solve is actually easy. You can make it call the List.remove(Object)
by
alphabets.remove((Character) inp);
Some other improvements:
Set
instead of List
in this case.boolean[26]
to keep track of whether an alphabet has appearedstr.charAt(index)
will give you the character at certain position.答案 6 :(得分:4)
一个整数变量足以存储此信息。你可以这样做
public static boolean check(String input) {
int result = 0;
input = input.toLowerCase();
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if (c >= 'a' && c <= 'z') {
result |= 1 << (input.charAt(i) - 'a');
}
}
return result == 0x3ffffff;
}
每个位对应一个英文字母的字母。因此,如果您的字符串包含所有字母,则结果将为00000011111111111111111111111111
答案 7 :(得分:3)
How about creating
List<String> alphabets = new ArrayList <String> ();
and add values as strings
then
for (String val : alphabets) { // if str is long this will be more effecient
if (str.contains (val) == false) {
System.out.println ("FAIL");
break;
}
}
答案 8 :(得分:3)
您可以通过更改代码中的此行来摆脱异常
char inp = strChar[i];
到
Character inp = strChar[i];
参考https://docs.oracle.com/javase/7/docs/api/java/util/List.html#remove(java.lang.Object)
List.remove('char')
被视为List.remove('int')
,这就是为什么你得到indexOutOfBoundsException,因为它正在检查'a'的ASCII
值为97.将变量'inp'转换为角色会打电话给List.remove('Object')
api。
答案 9 :(得分:2)
And if you like Java 8 streams like me:
final List<String> alphabets = new ArrayList<>();
And after filling alphabets with a-z:
final String str = "a dog is running crazily on the ground who doesn't care about the world";
final String strAsLowercaseAndWithoutOtherChars = str.toLowerCase()
.replaceAll("[^a-z]", "");
final boolean anyCharNotFound = alphabets.parallelStream()
.anyMatch(t -> !strAsLowercaseAndWithoutOtherChars.contains(t));
if (anyCharNotFound) {
System.out.println("String DOESN'T contains all alphabets");
} else {
System.out.println("String contains all alphabets");
}
This converts the string to lower case (skip if you really are only looking for the small letters), removes all characters from the string which are not small letters and then checks for all members of your alphabets
if they are contained in the string by using a parallel stream.
答案 10 :(得分:1)
对于Java 8,它可以写成:
boolean check(final String input) {
final String lower = input.toLowerCase();
return IntStream.range('a', 'z'+1).allMatch(a -> lower.indexOf(a) >= 0);
}
答案 11 :(得分:1)
做一些像
这样的事情sentence.split().uniq().sort() == range('a', 'z')
答案 12 :(得分:1)
这是另一种天真的解决方案,它使用String.split("")
将每个字符拆分为String[]
数组,然后Arrays.asList()
将其转换为List<String>
。然后,您只需致电yourStringAsList.containsAll(alphabet)
即可确定您的String
是否包含字母:
String yourString = "the quick brown fox jumps over the lazy dog";
List<String> alphabet = Arrays.asList("abcdefghijklmnopqrstuvwxyz".split(""));
List<String> yourStringAsList = Arrays.asList(yourString.split(""));
boolean containsAllLetters = yourStringAsList.containsAll(alphabet);
System.out.println(containsAllLetters);
这种方法可能不是最快的,但我认为代码比提出循环和流以及诸如此类的解决方案更容易理解。
答案 13 :(得分:0)
Character inp = strChar[i];
Use this instead of char
, List remove method have 2 overloaded methods , one with object and one with int .If you pass char its been treated as the int one.
答案 14 :(得分:0)
Convert the string to lower case or capitals. Then loop thru the equivalent ascii decimal values for A-Z or a-z and return false if not found in character array. You will have to cast the int to char.
答案 15 :(得分:0)
I've thought about playing with the ASCII codes of the characters.
String toCheck = yourString.toLowerCase();
int[] arr = new int[26];
for(int i = 0; i < toCheck.length(); i++) {
int c = ((int) toCheck.charAt(i)) - 97;
if(c >= 0 && c < 26)
arr[c] = arr[c] + 1;
}
After running the loop you eventually get an array of counters, each representing a letter of alphabet (index) and it's occurrence in the string.
boolean containsAlph = true;
for(int i = 0; i < 26; i++)
if(arr[i] == 0) {
containsAlph = false;
break;
}