java 如何检查字符串是否包含字母表中的所有字母?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39263751/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 04:13:50  来源:igfitidea点击:

How to check if a string contains all the letters of the alphabet?

javastringarraylist

提问by Siddharth

I am trying to check if a string contains all the letters of the alphabet. I created an ArrayListwhich contains the whole alphabet. I converted the string to char array and I'm iterating through the character array, and for every character present in the ArrayListI'm removing an element from it. And in the end, I'm trying to check if the Arraylistis empty to see if all elements have been removed. That would indicate the string contains all the letters of the alphabet.

我试图检查一个字符串是否包含字母表中的所有字母。我创建了一个ArrayList包含整个字母表的。我将字符串转换为字符数组,并遍历字符数组,对于存在于其中的每个字符,ArrayList我正在从中删除一个元素。最后,我试图检查 是否Arraylist为空以查看是否已删除所有元素。这将表明该字符串包含字母表中的所有字母。

Unfortunately, the code is throwing IndexOutOfBoundsExceptionerror inside the if condition where I'm removing elements from the arraylist

不幸的是,代码IndexOutOfBoundsException在 if 条件中抛出错误,我正在从数组列表中删除元素

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");

回答by Rogue

All these solutions seem to do a lot of work for a relatively simple check, especially given Java 8's stream API:

所有这些解决方案似乎都为相对简单的检查做了很多工作,特别是考虑到 Java 8 的流 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 while still using streams, then you can keep track with a HashSetinternally:

如果您想在仍然使用流的情况下在找到整个字母表后立即结束字符串迭代,那么您可以使用HashSet内部跟踪:

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 Setis filled with the 26 required characters.

这样,只要Set填充了 26 个所需的字符,流就会停止。

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.

在下面的性能方面有一些(甚至仍然)更有效的解决方案,但作为个人笔记,我会说不要过多地陷入过早优化,在那里你可以获得可读性并减少编写实际代码的工作量。

回答by Leon

List.removeremoves by index. Since a charcan 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.

List.remove按索引删除。由于 achar可以转换为 int,因此您可以有效地删除不存在的索引值,即 char 'a' 等于 int 97。正如您所见,您的列表没有 97 个条目。

You can do alphabet.remove(alphabets.indexOf(inp));

你可以做到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

正如@Scary Wombat(https://stackoverflow.com/a/39263836/1226744)和@Kevin Esche(https://stackoverflow.com/a/39263917/1226744)所指出的,你的算法有更好的替代方案

回答by hahn

O(n) solution

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;
                }
            }
        }
    }
}

回答by TheLostMind

Regex is your friend. No need to use a Listhere.

正则表达式是你的朋友。无需在List此处使用 a 。

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

}

回答by SomeJavaGuy

Adding to @Leon answer, creating a Listand 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 Stringto 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.

添加到@Leon 答案中,创建 aList并从中删除似乎是不必要的。您可以简单地循环'a' - 'z'并检查 each char。此外,您正在遍历整个String以找出每个字母是否存在。但更好的版本是遍历每个字母本身。这可以潜在地保护您几次迭代。

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");

回答by Adrian Shum

Another answer has already pointed out the reason for exception. You have misused List.remove(), as it implicitly convert charto intwhich it called the List.remove(int)which remove by index.

另一个答案已经指出了例外的原因。您误用了List.remove(),因为它隐式转换charint,它调用List.remove(int)which 删除按索引。

The way to solve is actually easy. You can make it call the List.remove(Object)by

解决的方法其实很简单。你可以把它称之为List.remove(Object)

alphabets.remove((Character) inp);

Some other improvements:

其他一些改进:

  1. You should use Setinstead of Listin this case.
  2. You can even use a boolean[26]to keep track of whether an alphabet has appeared
  3. You do not need to convert your string to char array. Simply do a str.charAt(index)will give you the character at certain position.
  1. 在这种情况下,您应该使用Set代替List
  2. 您甚至可以使用 aboolean[26]来跟踪是否出现了字母表
  3. 您不需要将字符串转换为字符数组。简单地做一个str.charAt(index)会给你特定位置的角色。

回答by cliffroot

One integer variable is enough to store this information. You can do it like this

一个整数变量足以存储此信息。你可以这样做

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;
}

Each bit corresponds to a letter in English alphabet. So if your string contains all letters the result will be of form 00000011111111111111111111111111

每个位对应于英文字母表中的一个字母。因此,如果您的字符串包含所有字母,则结果将采用以下形式00000011111111111111111111111111

回答by Arathi Senan

You can get rid of the exception, by changing this line in your code

您可以通过更改代码中的这一行来摆脱异常

char inp = strChar[i];

to

Character inp = strChar[i];

Refer https://docs.oracle.com/javase/7/docs/api/java/util/List.html#remove(java.lang.Object)

参考https://docs.oracle.com/javase/7/docs/api/java/util/List.html#remove(java.lang.Object)

List.remove('char')is treated as List.remove('int'), which is why you are getting indexOutOfBoundsException, because it is checking the ASCIIvalue of 'a' which is 97. Converting variable 'inp' to Character would call List.remove('Object')api.

List.remove('char')被视为List.remove('int'),这就是您收到 indexOutOfBoundsException 的原因,因为它正在检查ASCII'a'的值,即 97。将变量 'inp' 转换为 Character 将调用List.remove('Object')api。

回答by Scary Wombat

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;
     }
}

回答by Florian Link

And if you like Java 8 streams like me:

如果你像我一样喜欢 Java 8 流:

final List<String> alphabets = new ArrayList<>();

And after filling alphabets with a-z:

用 az 填充字母后:

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 alphabetsif they are contained in the string by using a parallel stream.

这会将字符串转换为小写(如果您真的只是在寻找小写字母,则跳过),从字符串中删除所有非小写字母的字符,然后alphabets使用并行流。