Biorąc pod uwagę ciąg „ThisStringHasNoSpacesButItDoesHaveCapitals”, jaki jest najlepszy sposób dodawania spacji przed dużymi literami. Zatem końcowy ciąg to „Ten ciąg nie ma spacji, ale ma wielkie litery”
Oto moja próba z RegEx
System.Text.RegularExpressions.Regex.Replace(value, "[A-Z]", " $0")
Odpowiedzi:
Wyrażenia regularne będą działały dobrze (głosowałem nawet za odpowiedzią Martina Browna), ale są one drogie (i osobiście uważam, że każdy wzór jest dłuższy niż kilka znaków, które są zbyt tępe)
Ta funkcja
Zrobi to 100 000 razy w 2966750 tyknięć, regex zajmie 25 000 000 tyknięć (i to po skompilowaniu wyrażenia regularnego).
Jest lepiej, dla danej wartości lepszej (tj. Szybszej), ale to więcej kodu do utrzymania. „Lepszy” to często kompromis konkurencyjnych wymagań.
Mam nadzieję że to pomoże :)
Aktualizacja
Minęło sporo czasu, odkąd na to spojrzałem, i właśnie zdałem sobie sprawę, że czasy nie zostały zaktualizowane, ponieważ kod się zmienił (zmienił się tylko trochę).
W ciągu z powtarzającym się 100 razy „Abbbbbbbbb” (tj. 1000 bajtów) 100 000 konwersji pobiera ręcznie kodowaną funkcję 4517177 tyknięć, a poniższy Regeks zajmuje 59 435 719, dzięki czemu funkcja kodowana ręcznie działa w 7,6% czasu Regex.
Aktualizacja 2 Czy weźmie pod uwagę akronimy? Teraz będzie! Logika instrukcji if jest dość niejasna, ponieważ można ją rozszerzyć do tego ...
... wcale nie pomaga!
Oto oryginalna prosta metoda, która nie martwi się o akronimy
źródło
Twoje rozwiązanie ma problem polegający na tym, że wstawia spację przed pierwszą literą T, aby uzyskać
Aby obejść ten problem, poszukaj również małej litery poprzedzającej ją, a następnie wstaw spację na środku:
Edycja 1:
Jeśli użyjesz
@"(\p{Ll})(\p{Lu})"
go , zbierze także znaki akcentowane.Edycja 2:
Jeśli twoje ciągi mogą zawierać akronimy, możesz użyć tego:
Zatem „DriveIsSCSICompatible” staje się „Drive is SCSI Compatible”
źródło
"([^A-Z\\s])([A-Z])"
, nawet z akronimami?Nie testowałem wydajności, ale tutaj w jednej linii z linq:
źródło
Wiem, że to stary, ale jest to rozszerzenie, którego używam, gdy muszę to zrobić:
Umożliwi to użycie
MyCasedString.ToSentence()
źródło
TrimStart(' ')
go dodasz , usuniesz wiodącą przestrzeń.SelectMany
które zawiera indeks, w ten sposób unika pierwszej litery i niepotrzebnego potencjalnego obciążenia dodatkowego połączenia zTrimStart(' ')
. Obrabować.Postanowiłem stworzyć prostą metodę rozszerzenia opartą na kodzie Binary Worriera, który będzie poprawnie obsługiwał akronimy i jest powtarzalny (nie będzie zniekształcał już spacji). Oto mój wynik.
Oto przypadki testów jednostkowych, które funkcja ta spełnia. Do tej listy dodałem większość sugerowanych przypadków tchrista. Trzy z tych, których nie przejdzie (dwa są tylko cyframi rzymskimi) są komentowane:
źródło
Witamy w Unicode
Wszystkie te rozwiązania są zasadniczo niewłaściwe dla nowoczesnego tekstu. Musisz użyć czegoś, co rozumie wielkość liter. Ponieważ Bob poprosił o inne języki, dam Perlowi parę.
Dostarczam cztery rozwiązania, od najgorszego do najlepszego. Tylko najlepszy jest zawsze odpowiedni. Inni mają problemy. Oto test, aby pokazać, co działa, a co nie i gdzie. Użyłem znaków podkreślenia, aby zobaczyć, gdzie zostały wstawione spacje, i oznaczyłem jako niewłaściwe wszystko, co jest, no cóż, złe.
BTW, prawie wszyscy tutaj wybrali pierwszy sposób, ten oznaczony jako „Najgorszy”. Kilku wybrało drugi sposób, oznaczony „OK”. Ale nikt przede mną nie pokazał ci, jak zastosować podejście „lepsze” lub „najlepsze”.
Oto program testowy z czterema metodami:
Jeśli uzyskasz wynik taki sam, jak „Najlepszy” w tym zestawie danych, będziesz wiedział, że zrobiłeś to poprawnie. Do tego czasu nie. Nikt tutaj nie zrobił nic lepszego niż „Ok”, a większość zrobiła to „Najgorszy”. Nie mogę się doczekać, aż ktoś opublikuje poprawny kod ℂ♯.
Zauważyłem, że kod wyróżniający StackOverflow jest znowu żałośnie głupi. Robią to samo stare kulawizny, jak (większość, ale nie wszystkie) spośród pozostałych podejść, o których tu mowa. Czy nie minęło już dużo czasu, aby położyć ASCII na odpoczynek? To już nie ma sensu, a udawanie, że wszystko, co masz, jest po prostu złe. To powoduje zły kod.
źródło
Binarny Worrier, użyłem twojego sugerowanego kodu i jest raczej dobry, mam tylko jeden drobny dodatek:
Dodałem warunek
!char.IsUpper(text[i - 1])
. Naprawiono błąd, który powodował, że coś takiego jak „AverageNOX” zamieniało się w „Average NO X”, co jest oczywiście błędne, ponieważ powinno brzmieć „Average NOX”.Niestety nadal ma to błąd, że jeśli masz tekst „FromAStart”, wyjmiesz „From AStart”.
Czy są jakieś przemyślenia na temat rozwiązania tego problemu?
źródło
if (char.IsUpper(text[i]) && !(char.IsUpper(text[i - 1]) && char.IsUpper(text[i + 1])))
Wynik testu: „From Start”, „From THE Start”, „From A Start”, ale musiszi < text.Length - 1
w stanie pętli for zignorować ostatni znak i zapobiec wyjątkowi poza zakresem.To moje:
źródło
<pre><code>code</code></pre>
bloku zamiast składni Markdown. Nie musisz go głosować (jeśli to byłeś ty).Upewnij się, że nie są umieszczenie spacji na początku łańcucha, ale są umieszczając je pomiędzy kolejnymi literami. Niektóre odpowiedzi tutaj nie dotyczą jednego lub obu tych punktów. Istnieją inne sposoby niż wyrażenia regularne, ale jeśli wolisz z nich korzystać, spróbuj tego:
\B
Jest negowane\b
, więc to oznacza nie-słowo-granica. Oznacza to, że wzorzec pasuje do „Y” wXYzabc
, ale nie wYzabc
lubX Yzabc
. Jako niewielki bonus możesz użyć tego na sznurku ze spacjami i nie podwoi ich.źródło
Regex umieszcza spację przed każdą wielką literą:
Uważaj na miejsce z przodu, jeśli „1 $ 2 $”, to właśnie to zrobi.
Oto wynik:
źródło
"([A-Z0-9])([a-z]*)"
To, co masz, działa idealnie. Pamiętaj tylko, aby ponownie przypisać
value
wartość zwracaną przez tę funkcję.źródło
Oto jak możesz to zrobić w SQL
źródło
Inspirowany @MartinBrown, Two Lines of Simple Regex, który rozpozna twoje imię, w tym Acyronimy w dowolnym miejscu ciągu.
źródło
źródło
źródło
W Ruby za pośrednictwem Regexp:
źródło
Wziąłem Kevin Strikers doskonałe rozwiązanie i przeszedłem na VB. Ponieważ jestem zamknięty w .NET 3.5, musiałem również napisać IsNullOrWhiteSpace. To przechodzi wszystkie jego testy.
źródło
Pytanie jest nieco stare, ale obecnie w Nuget jest ładna biblioteka, która robi dokładnie to samo, a także wiele innych konwersji na tekst czytelny dla ludzi.
Sprawdź Humanizer na GitHub lub Nuget.
Przykład
źródło
Wydaje się, że to dobra okazja
Aggregate
. Zostało to zaprojektowane tak, aby było czytelne, niekoniecznie szczególnie szybkie.źródło
Oprócz odpowiedzi Martina Browna miałem również problem z liczbami. Na przykład: „Lokalizacja 2” lub „Jan22” powinny być odpowiednio „Lokalizacja 2” i „22 stycznia”.
Oto moje wyrażenie regularne do zrobienia tego, używając odpowiedzi Martina Browna:
Oto kilka świetnych stron, na których można dowiedzieć się, co oznacza każda część:
Analizator wyrażeń regularnych oparty na Javie (ale działa z większością wyrażeń regularnych .net)
Analizator oparty na skryptach akcji
Powyższe wyrażenie regularne nie będzie działać na stronie skryptu akcji, chyba że zastąpisz wszystkie
\p{Ll}
z[a-z]
,\p{Lu}
z[A-Z]
i\p{Nd}
z[0-9]
.źródło
Oto moje rozwiązanie, oparte na sugestii Binary Worriers i budowaniu w komentarzach Richarda Priddysa, ale także biorąc pod uwagę, że w podanym ciągu może istnieć biała przestrzeń, więc nie doda białej przestrzeni obok istniejącej białej przestrzeni.
źródło
Dla każdego, kto szuka funkcji C ++ odpowiadającej na to samo pytanie, możesz skorzystać z poniższych. Jest to wzorowane na odpowiedzi udzielonej przez @Binary Worrier. Ta metoda automatycznie zachowuje akronimy.
Ciągi testów, których użyłem dla tej funkcji, a wyniki to:
źródło
Rozwiązanie C # dla ciągu wejściowego, który składa się tylko ze znaków ASCII. Wyrażenie regularne zawiera negatywny wygląd, aby zignorować wielką (wielką) literę, która pojawia się na początku łańcucha. Używa Regex.Replace () do zwrócenia pożądanego ciągu.
Zobacz także demo regex101.com .
Oczekiwany wynik:
Aktualizacja: Oto odmiana, która będzie również obsługiwać akronimy (ciągi wielkich liter).
Zobacz także demo regex101.com i demo ideone.com .
Oczekiwany wynik:
źródło
Oto dokładniejsze rozwiązanie, które nie umieszcza spacji przed słowami:
Uwaga: użyłem wielu wyrażeń regularnych (nie jest to zwięzłe, ale będzie również obsługiwać akronimy i słowa jednoliterowe)
W :
Out :
źródło
Wszystkie poprzednie odpowiedzi wyglądały na zbyt skomplikowane.
Miałem ciąg znaków, który miał kombinację wielkich liter i _ użytego, string.Replace (), aby utworzyć _, „” i użyłem następującego, aby dodać spację do wielkich liter.
źródło
Zainspirowany odpowiedzią Binary Worriera rzuciłem się na to.
Oto wynik:
Wykonano test przy użyciu stopera z uruchomionymi 10000000 iteracjami oraz różnymi długościami i kombinacjami łańcuchów.
Średnio 50% (może nieco więcej) szybciej niż odpowiedź Binary Worrier.
źródło
źródło
Ten zawiera akronimy i liczby mnogie akronimów i jest nieco szybszy niż zaakceptowana odpowiedź:
Przechodzi te testy:
źródło
Implementacja
fold
, znana również jakoAggregate
:Oprócz żądania ta implementacja poprawnie zapisuje wiodące, wewnętrzne, końcowe spacje i akronimy, na przykład
źródło
Prosty sposób dodawania spacji po małych i dużych literach lub cyfrach.
źródło