Jak mogę sprawdzić, czy pojedynczy znak pojawia się w ciągu?

210

W Javie jest sposób na sprawdzenie warunku:

„Czy ten pojedynczy znak w ogóle pojawia się w ciągu x”

bez użycia pętli?

barfoon
źródło
4
Czy jest jakiś konkretny powód, dla którego próbujesz unikać pętli?
shsteimer
2
Nie można przeprowadzić ogólnego wyszukiwania znaku bez pętli. Sprawdź, jak działa maszyna Turinga.
Salvador Valencia,
4
Powinniśmy założyć, że @barfoon nie chce, aby pętla była w ich kodzie. Oczywiście maszyna gdzieś się zapętla. W przeciwnym razie pytanie jest nonsensowne.
WW.
Powiedziałbym, że manipulacja ciągiem java jest dość ograniczona
ACV

Odpowiedzi:

276

Możesz użyć string.indexOf('a').

Jeśli znak ajest obecny w string:

zwraca indeks pierwszego wystąpienia znaku w sekwencji znaków reprezentowanej przez ten obiekt lub -1, jeśli znak nie występuje.

poseł.
źródło
8
Ale za tym połączeniem zawsze kryje się pętla, ponieważ inaczej nie można znaleźć symbolu.
vava
4
indexOf () używa pętli wewnętrznie.
mmcdole,
22
Nie o to pytał Barfoon. B chce uniknąć wykonywania pętli w kodzie B. Oczywiście interfejs API musi wykonać pętlę, ponieważ String to tablica znaków zamknięta w ładnej klasie z wieloma przydatnymi metodami.
mP.
5
W jaki sposób te odpowiedzi zyskują tak wiele pozytywnych opinii? Rozwiązania użycia indexOf()używa pętli wewnętrznie. Żadna z odpowiedzi nie daje poprawnego rozwiązania, a jeśli ktoś odważy się zadać nowe pytanie, ludzie to deklarują Duplicate. Naprawdę rozczarowujące; (
Prashant Prabhakar Singh
4
@PrashantPrabhakarSingh Nie widzę, jak można to zrobić bez pętli. Łańcuch jest mniej więcej grupą znaków. Jeśli jest to grupa (kolekcja, tablica itp.), Bez względu na to, czy jest ona wewnętrzna, czy zewnętrzna względem kodu natywnego, oczekiwałbym, że potrzebujesz pętli, aby znaleźć coś w „grupie”. Wierzę „bez użycia pętli?” jest bardziej jak „bez pisania własnej pętli?”.
Tyler
145
  • String.contains() która sprawdza, czy ciąg zawiera określoną sekwencję wartości char
  • String.indexOf() który zwraca indeks w ciągu pierwszego wystąpienia określonego znaku lub podłańcucha (istnieją 4 odmiany tej metody)
Zach Scrivena
źródło
15
char nie jest CharSequence, więc nie można go przekazać do String.contains (CharSequence).
mP.
28
Aby użyć String.contains () z pojedynczym char c, wykonaj następujące czynności: String.contains (Character.toString (c))
friederbluemle 19.09
7
Lub zrób to, jeśli lubisz krótki kod:String.contains(""+c)
Felix Neumeyer
31

Nie jestem pewien, o co dokładnie pyta oryginalny plakat. Ponieważ zarówno indexOf (...), jak i zawiera (...) prawdopodobnie używają pętli wewnętrznie, być może chce sprawdzić, czy jest to w ogóle możliwe bez pętli? Mogę myśleć o dwóch sposobach z ręki, jednym z nich byłaby oczywiście rekurencja:

public boolean containsChar(String s, char search) {
    if (s.length() == 0)
        return false;
    else
        return s.charAt(0) == search || containsChar(s.substring(1), search);
}

Drugi jest znacznie mniej elegancki, ale kompletność ...:

/**
 * Works for strings of up to 5 characters
 */
public boolean containsChar(String s, char search) {
    if (s.length() > 5) throw IllegalArgumentException();

    try {
        if (s.charAt(0) == search) return true;
        if (s.charAt(1) == search) return true;
        if (s.charAt(2) == search) return true;
        if (s.charAt(3) == search) return true;
        if (s.charAt(4) == search) return true;
    } catch (IndexOutOfBoundsException e) {
        // this should never happen...
        return false;
    }
    return false;
}

Liczba linii rośnie, ponieważ trzeba oczywiście obsługiwać coraz dłuższe ciągi. Ale w ogóle nie ma pętli / rekurencji. Możesz nawet usunąć kontrolę długości, jeśli obawiasz się, że ta długość () używa pętli.

Jack Leow
źródło
10
Jeśli zdefiniujesz rekurencję jako procedurę niepętlową, jesteś maniakiem: D +1 za bycie kreatywnym.
guerda
1
To wszystko jest dobre dla zakodowanej długości 5. W przeciwnym razie istnieje potrzeba wykonania pętli, aby wyszukać postać. Nie być pedantycznym, ale dowodem na to jest definicja maszyny Turinga. Podstawa urządzenia obliczeniowego.
Salvador Valencia,
4
Popraw mnie, jeśli się mylę, wydaje mi się, że pod koniec dnia rekursja to ukryta pętla, prawda? W niektórych sytuacjach może to prowadzić do większego zużycia pamięci niż zwykła pętla.
PasinduJay
12
String temp = "abcdefghi";
if(temp.indexOf("b")!=-1)
{
   System.out.println("there is 'b' in temp string");
}
else
{
   System.out.println("there is no 'b' in temp string");
}
Richard
źródło
1
czy nie jest to dokładna kopia zaakceptowanej odpowiedzi? doceniamy twój wysiłek, ale powinieneś spróbować znaleźć jakieś pytanie bez odpowiedzi i na nie odpowiedzieć.
Shekhar_Pro
7

Możesz użyć 2 metod z Stringklasy.

  • String.contains() która sprawdza, czy ciąg zawiera określoną sekwencję wartości char
  • String.indexOf() który zwraca indeks w ciągu pierwszego wystąpienia określonego znaku lub podłańcucha lub zwraca -1, jeśli znak nie zostanie znaleziony (istnieją 4 odmiany tej metody)

Metoda 1:

String myString = "foobar";
if (myString.contains("x") {
    // Do something.
}

Metoda 2:

String myString = "foobar";
if (myString.indexOf("x") >= 0 {
    // Do something.
}

Linki: Zach Scrivena

Halfacht
źródło
4

Aby sprawdzić, czy coś nie istnieje w ciągu, musisz przynajmniej spojrzeć na każdy znak w ciągu. Więc nawet jeśli nie użyjesz wyraźnie pętli, będzie ona miała taką samą wydajność. To powiedziawszy, możesz spróbować użyć str.contains („” + char).

słodycze
źródło
Zgoda. W pewnym momencie ktoś gdzieś musi zbudować pętlę, aby to zrobić. Na szczęście robi to Java API, inaczej nasz kod byłby bardzo zagracony!
Fortyrunner,
4

Jeśli musisz często sprawdzać ten sam ciąg znaków, możesz z góry obliczyć występowanie postaci. Jest to implementacja wykorzystująca tablicę bitów zawartą w długiej tablicy:

public class FastCharacterInStringChecker implements Serializable {
private static final long serialVersionUID = 1L;

private final long[] l = new long[1024]; // 65536 / 64 = 1024

public FastCharacterInStringChecker(final String string) {
    for (final char c: string.toCharArray()) {
        final int index = c >> 6;
        final int value = c - (index << 6);
        l[index] |= 1L << value;
    }
}

public boolean contains(final char c) {
    final int index = c >> 6; // c / 64
    final int value = c - (index << 6); // c - (index * 64)
    return (l[index] & (1L << value)) != 0;
}}
filumina
źródło
Wypróbowałem twoje rozwiązanie podobnego problemu, jaki mam. Moje najbliższe rozwiązanie to ponad 1500 milisekund dla stringa o długości 63k i string2 o długości 95k. Twoje rozwiązanie wyrzuca wynik w 3-5 milisekund. Czy możesz edytować swoje rozwiązanie, aby zawierało wyjaśnienie? Proszę?
Viorel Florian
1
package com;
public class _index {

    public static void main(String[] args) {
        String s1="be proud to be an indian";
        char ch=s1.charAt(s1.indexOf('e'));
        int count = 0; 
        for(int i=0;i<s1.length();i++) {
            if(s1.charAt(i)=='e'){
                System.out.println("number of E:=="+ch);
                count++;
            }
        }
        System.out.println("Total count of E:=="+count);
    }
}
Praveen Kumar
źródło
2
i fornie jest teraz pętlą?
Mindwin
0
String s="praveen";
boolean p=s.contains("s");
if(p)
    System.out.println("string contains the char 's'");
else
    System.out.println("string does not contains the char 's'");

Wynik

string does not contains the char 's'
praveen
źródło
Ta sama odpowiedź została udzielona wcześniej.
Serge Belov,
0
static String removeOccurences(String a, String b)
{
    StringBuilder s2 = new StringBuilder(a);

    for(int i=0;i<b.length();i++){
        char ch = b.charAt(i);  
        System.out.println(ch+"  first index"+a.indexOf(ch));

        int lastind = a.lastIndexOf(ch);

    for(int k=new String(s2).indexOf(ch);k > 0;k=new String(s2).indexOf(ch)){
            if(s2.charAt(k) == ch){
                s2.deleteCharAt(k);
        System.out.println("val of s2 :             "+s2.toString());
            }
        }
      }

    System.out.println(s1.toString());

    return (s1.toString());
}
Ganeshmani
źródło
W tym miejscu szukamy wystąpienia każdego znaku z ciągu b obecnego w ciągu a i usuwania znaków.
Ganeshmani
0
you can use this code. It will check the char is present or not. If it is present then the return value is >= 0 otherwise it's -1. Here I am printing alphabets that is not present in the input.

import java.util.Scanner;

public class Test {

public static void letters()
{
    System.out.println("Enter input char");
    Scanner sc = new Scanner(System.in);
    String input = sc.next();
    System.out.println("Output : ");
    for (char alphabet = 'A'; alphabet <= 'Z'; alphabet++) {
            if(input.toUpperCase().indexOf(alphabet) < 0) 
                System.out.print(alphabet + " ");
    }
}
public static void main(String[] args) {
    letters();
}

}

//Ouput Example
Enter input char
nandu
Output : 
B C E F G H I J K L M O P Q R S T V W X Y Z
Nandu cg
źródło
0

Czy poniżej tego szukasz?

int index = string.indexOf(character);
return index != -1 && string.lastIndexOf(character) != index;
Toochka
źródło
Dlaczego masz && string.lastIndexOf(character) != index
GreenAsJade
-1

Nie będziesz w stanie sprawdzić, czy znak w ogóle pojawia się w jakimś łańcuchu, nie przechodząc przynajmniej raz po nim przy użyciu pętli / rekurencji (wbudowane metody takie jak indexOf również używają pętli)

Jeśli nie razy sprawdzasz, czy znak jest w ciągu x, jest więcej niż długość ciągu, niż zaleciłbym użycie struktury danych Set , ponieważ byłoby to bardziej wydajne niż zwykłe użycieindexOf

String s = "abc";

// Build a set so we can check if character exists in constant time O(1)
Set<Character> set = new HashSet<>();
int len = s.length();
for(int i = 0; i < len; i++) set.add(s.charAt(i));

// Now we can check without the need of a loop
// contains method of set doesn't use a loop unlike string's contains method
set.contains('a') // true
set.contains('z') // false

Za pomocą zestawu będziesz mógł sprawdzić, czy znak istnieje w ciągu w stałym czasie O (1), ale użyjesz również dodatkowej pamięci (złożoność przestrzeni będzie wynosić O (n)).

Dhyey
źródło
-3

Użyłem do tego metody string.include (), która zwraca true lub false, jeśli łańcuch lub znak zostanie znaleziony. Zobacz poniższą dokumentację.

https://www.w3schools.com/jsref/jsref_includes.asp

Udugam
źródło
Chociaż ten link może odpowiedzieć na pytanie, lepiej jest dołączyć tutaj istotne części odpowiedzi i podać link w celach informacyjnych. Odpowiedzi zawierające tylko łącze mogą stać się nieprawidłowe, jeśli połączona strona ulegnie zmianie.
Adriano Martins
2
Ta odpowiedź dotyczy JavaScript, pytanie konkretnie brzmi w języku Java
Hazem Farahat
-4

// to tylko główny ... możesz użyć uskrzydlonego czytnika lub skanera

string s;
int l=s.length();
int f=0;
for(int i=0;i<l;i++)
   {
      char ch1=s.charAt(i); 
      for(int j=0;j<l;j++)
         {
          char ch2=charAt(j);
          if(ch1==ch2)
           {
             f=f+1;
             s.replace(ch2,'');
           }
          f=0;
          }
     }
//if replacing with null does not work then make it space by using ' ' and add a if condition on top.. checking if its space if not then only perform the inner loop... 
w dowolnym momencie
źródło