web-dev-qa-db-ja.com

文字列にアルファベットのすべての文字が含まれているかどうかを確認するにはどうすればよいですか?

文字列にアルファベットのすべての文字が含まれているかどうかを確認しようとしています。アルファベット全体を含むArrayListを作成しました。文字列をchar配列に変換し、文字配列を反復処理し、ArrayListに存在するすべての文字に対して要素を削除しています。最後に、Arraylistが空かどうかを確認して、すべての要素が削除されたかどうかを確認しようとしています。これは、文字列にアルファベットのすべての文字が含まれていることを示します。

残念ながら、コードはarraylistから要素を削除するif条件内でIndexOutOfBoundsExceptionエラーをスローしています

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

これらのソリューションはすべて、特にJava 8のストリームAPI:

/* Your lowercase string */.chars()
    .filter(i -> i >= 'a' && i <= 'z')
    .distinct().count() == 26;

編集:速度のため

ストリームの使用中にアルファベット全体が見つかったらすぐに文字列の反復を終了する場合は、内部で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

この方法では、Setが26個の必須文字で満たされるとすぐにストリームが停止します。

以下のパフォーマンスの観点から(さらには)より効率的なソリューションがいくつかありますが、個人的なメモとして、早すぎる最適化にとらわれすぎないようにしてください。

76
Rogue

_List.remove_はインデックスで削除します。 charはintにキャストできるため、存在しないインデックス値を効果的に削除します。つまり、char 'a'はint 97に等しくなります。ご覧のとおり、リストには97のエントリがありません。

alphabet.remove(alphabets.indexOf(inp));を実行できます。

@Scary Wombat( https://stackoverflow.com/a/39263836/1226744 )および@Kevin Esche( https://stackoverflow.com/a/39263917/ 1226744 )、あなたのアルゴリズムのより良い代替手段があります

16
Leon

正規表現あなたの友達です。ここでListを使用する必要はありません。

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

}
9
TheLostMind

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

@Leonの回答に追加して、Listを作成し、そこから削除することはまったく不要なようです。単に'a' - 'z'をループし、各charでチェックを行うことができます。さらに、各文字が存在するかどうかを確認するためにString全体をループしています。しかし、より良いバージョンは、各文字自体をループすることです。これにより、数回の反復を強力に安全にすることができます。

最後に、簡単な例は次のようになります。

// 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");
8
SomeJavaGuy

別の答えはすでに例外の理由を指摘しています。 List.remove()を暗黙的にcharからintに変換するため、List.remove(int)を誤って使用しました。

実際に解決する方法は簡単です。 List.remove(Object)を呼び出すようにするには

alphabets.remove((Character) inp);

その他の改善点:

  1. この場合、Setの代わりにListを使用する必要があります。
  2. boolean[26]を使用して、アルファベットが出現したかどうかを追跡することもできます
  3. 文字列をchar配列に変換する必要はありません。 str.charAt(index)を実行するだけで、特定の位置にキャラクターが表示されます。
5
Adrian Shum

この情報を保存するには、1つの整数変数で十分です。このようにできます

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

4
cliffroot

作成はどうですか

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

値を文字列として追加します

それから

for (String val : alphabets) {   // if str is long this will be more effecient
     if (str.contains (val) == false) {
        System.out.println ("FAIL");
        break;
     }
}
3
Scary Wombat

コードのこの行を変更することで、例外を取り除くことができます

_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を取得する理由です。これは、97である 'a'のASCII値をチェックしているためです。 'CharacterにList.remove('Object') apiを呼び出します。

3
Arathi Senan

そしてJava私のような8つのストリーム:

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

そして、アルファベットを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");
}

これは、文字列を小文字に変換し(実際に小さい文字だけを探している場合はスキップします)、小文字ではない文字列からすべての文字を削除し、alphabetsのすべてのメンバーをチェックします。並列ストリームを使用して文字列で。

2
Florian Link

Java 8の場合、次のように記述できます。

boolean check(final String input) {
    final String lower = input.toLowerCase();
    return IntStream.range('a', 'z'+1).allMatch(a -> lower.indexOf(a) >= 0);
}
1
j2ko

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

このアプローチは最速ではないかもしれませんが、コードはループやストリームなどを提案するソリューションよりも理解しやすいと思います。

1
Kevin Workman

次のようなことをしてください

sentence.split().uniq().sort() == range('a', 'z')
1
lblzsd
Character inp = strChar[i]; 

charの代わりにこれを使用します。Listremoveメソッドには2つのオーバーロードメソッドがあり、1つはオブジェクト、もう1つはintです。charを渡すと、intメソッドとして扱われます。

0
Rohit

文字列を小文字または大文字に変換します。次に、A-Zまたはa-zの同等のASCII 10進数値をループし、文字配列で見つからない場合はfalseを返します。 intをcharにキャストする必要があります。

0
Olga

文字のASCIIコードで遊ぶことを考えました。

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

ループを実行した後、最終的にカウンターの配列を取得します。各カウンターはアルファベット文字(インデックス)と文字列内での出現を表します。

boolean containsAlph = true;
for(int i = 0; i < 26; i++)
    if(arr[i] == 0) {
        containsAlph = false;
        break;
    }
0