Regex szukanie dokładnie jednego wystąpienia podanego znaku

Odpowiedz Nowy wątek
2019-08-22 18:50
0

Potrzebuje znaleźć w Stringu dokładnie jednego wystąpienia wybranego znaku.
Kombinuje tak

System.out.println(!txt1.matches("[^a]*"));

Jak już pewnie wiecie, nie zawsze daje odpowiedni wynik.

[^a]{1}...? - Spearhead 2019-08-22 19:20

Pozostało 580 znaków

2019-08-22 19:01
1

Czy próbujesz dostać informację, że jakiś znak występuje w tekście dokładnie jeden raz? Dziwne to Twoje zdanie i wole się upewnić :)
Jeśli tak, to gugle mi podpowiedział dosyć szybko: "^[^a]*a[^a]*$"

edytowany 1x, ostatnio: baant, 2019-08-22 19:11

Pozostało 580 znaków

2019-08-22 19:17
2

Polecam sprawdzić swoje wyrażenie w parserze wyrażeń, np. http://regexr.com/. Był ostatnio temat na forum, https://4programmers.net/Forum/Hardware_Software/330029-programowy_tester_edytor_wyrazen_regularnych.
Jeśli dobrze rozumiem co autor miał na myśli, to nie potrzeba tu wyrażenia. Lepiej zrobić tak: text.contains("a"). Metoda contains odpowiada na pytanie czy podany ciąg znaków znajduje się w tym, którego metoda się tyczy - nieważne w jakim miejscu i nieważne ile razy - ważne, że jest. Opis metody https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#contains(java.lang.CharSequence)
A jeśli już koniecznie chce regex, to tak System.out.println(txt1.matches("[a]"));. Gwiazdka może byłaby spoko, bo każe znaleźć dowolną liczbę podanego znaku. Ale za to [^a] oznacza negację. Czyli wychodzi nam niespodzianka "znajdź dowolną liczbę czegoś, co nie jest znakiem a.

edytowany 1x, ostatnio: PerlMonk, 2019-08-22 19:19
W zadaniu chodzi o dokładnie jedno wystąpienie i nie więcej a contains zwróci true również jeśli wystąpień będzie więcej. Więc tylko rozwiązanie twojego przedmówcy pasuje. - manifestor 2019-08-22 19:35
Tylko problem z rozwiązaniem wyżej jest taki, że wyrażenie dopasuje cały tekst. - PerlMonk 2019-08-22 19:43

Pozostało 580 znaków

2019-08-22 19:56
baant napisał(a):

Czy próbujesz dostać informację, że jakiś znak występuje w tekście dokładnie jeden raz? Dziwne to Twoje zdanie i wole się upewnić :)
Jeśli tak, to gugle mi podpowiedział dosyć szybko: "^[^a]*a[^a]*$"

To wyrażenie spełni swoje zadanie, ale dopasuje przy okazji cały tekst. To już prościej nie używać regexa wcale:

boolean ok = false;
int a;

for (a = 0; a < text.length(); a++) {
    if (text.charAt(a) == 'a') {
        if (!ok) {
            ok = true;
        } else {
            ok = false;
            break;
        }
    }
}

Po co używać gwiazdek do prostych zadań?

Popieram. Dodatkowo zużycie RAM stałe, niemal zerowe, GC leniuchuje - AnyKtokolwiek 2019-08-22 22:01
Geniusz tkwi w prostocie :D - manifestor 2019-08-30 18:26
Dokładnie :D . Oczywiście to nie jest jedyne rozwiązanie, ale w tym przypadku zadziała. Dla długiego tekstu zadziała szybciej, niż regex, bo pominie część tekstu jeśli litera została znaleziona. Gwiazdki w wyrażeniach regularnych przydają się bardzo rzadko. - PerlMonk 2019-08-30 20:36

Pozostało 580 znaków

2019-08-22 20:12
1

Ogólnie, taki pseudo kod

str - dany tekst
key - badany znak

str. lastIndexOf(key) == str.firstIndexOf(key)
(first równy last bo wtedy wystąpił tylko jeden raz albo zero razy) i różny od -1 (bo to dało co najmniej jeden znaleziony a -1 zwracane jest kiedy klucz nie występuje w tekście)

Czy Java czy JS to sobie potem dobierasz kosmetykę składni itd.

Nie będę się upierać, że ma być -1 bo może w innym języku albo inna implementacja zwróci jakąś wartość < 0 kiedy nie znaleziono klucza.
Ale na interview ustne one to one takie rozwiązanie jak najbardziej będzie OK.

edytowany 5x, ostatnio: BraVolt, 2019-08-22 20:40
Nie widzę metody zwracającej index, pod którym znajduje się pierwsze wystąpienie (i mean firstIndexOf) - manifestor 2019-08-30 18:11
Ja głupi. Oczywiście, że jest string.indexOf() :D - manifestor 2019-08-30 19:20

Pozostało 580 znaków

2019-08-22 20:29
1

OT, warto używać dostępnych implementacji algorytmów i struktur danych z danego języka.

Np. podobne zadanie typu isUnique(array|string) - czy array|string nie ma powtarzających się wartości.
Zamiast latać O(n^2) pętlami (i się w stresie interview pomylić) jak nam na szybko przyszło do głowy rozwiązanie, można z danych wejściowych stworzyć Set, kiedy rozmiar otrzymanego Set jest równy licznie elementów wejściowych to są one unikatowe/unikalne (kurcze, polski analfabetym wtórny mnie dopadł - unique)

Modelowe O(n^2)

const isUnique = function (arr) {
    let result = true;

    for (let i = 0; i < arr.length; i++) {
        for (let j = 0; j < arr.length; j++) {
            if (i !== j && arr[i] === arr[j]) {
                result = false;
            }
        }
    }

    return result;
};

console.log(isUnique([1, 2, 3]));
console.log(isUnique([1, 1, 3]));
let numbers = [1, 2, 3];
console.log(new Set(numbers).size === numbers.length);

numbers = [1, 1, 3];
console.log(new Set(numbers).size === numbers.length);

Drugie podejście da się już zakodzić na szybko nawet w przeglądarce

A jak miałoby być na życzenie rekrutującego inżyniera wydajnie to prosty cache

const isUnique = function (arr) {
    const cache = {};

    for (let e of arr) {
        if (cache[e]) {
            return false;
        } else {
            cache[e] = true;
        }
    }

    return true;
};

Dla Javy zamiast obiektu {} będzie new HashMap(), w JS można tak samo z mapą

const isUnique = function (arr) {
    const cache = new Map();

    for (let e of arr) {
        if (cache.has(e)) {
            return false;
        } else {
            cache.set(e, true);
        }
    }

    return true;
};
edytowany 9x, ostatnio: BraVolt, 2019-08-22 22:11

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0