2016-04-29 18 views
5

Mam łańcuch wielbłądów, na przykład: JustAString.Dopasowywanie wielkich liter i uzupełnianie kolejnymi literami, aż do uzyskania określonej długości ciągu znaków

chciałbym tworzyć ciągi długości 4 wykonując następujące zasady:

  • złapać wszystkie litery;
  • jeśli masz więcej niż 4 duże litery, zachowaj tylko pierwsze 4;
  • jeśli mniej niż 4 litery, wykorzystać i dodać liter stanowiące kontynuację litera ostatni, aż długość staje 4.

Oto 3 przypadki, które mogą wystąpić:

  • ThisIsMyString przyniesie TIMS (wielkie litery);
  • ThisIsOneVeryLongString przyniesie TIOV (pierwsze 4 stolice);
  • MyString przyniesie MSTR (wielkie litery + tr skapitalizowane).

udało mi się rozwiązać dwóch pierwszych przypadkach z tym fragmencie:

str.scan(/[A-Z]/).first(4).join 

Jednak nie jestem pewien, w jaki sposób można najlepiej zmodyfikować powyższy fragment kodu do obsługi ostatnim przypadku również (a nawet spróbować coś innego).

P.S .: Gwarantuje się, że ciąg ma co najmniej jedną wielką literę i 4 znaki. Jeśli jednak teoretycznie brakuje kapitału, należy wziąć pod uwagę pierwsze 4 znaki. Jeśli nie ma 4 znaków, brakujące znaki mogą być wypełnione pierwszymi alfabetycznymi znakami (abcd). Ale, jak wspomniano, te przypadki 2 krawędzi zwykle się nie zdarzają.

Odpowiedz

4

zastąpić dowolny znak (ów), które poprzedza kapitał z niczym, a następnie chwycić pierwsze 4 znaki i konwersji małych liter :

str.gsub(/[^A-Z]+([A-Z])/){$1}[0..3].upcase

To nie obsługuje CAPI tals też. Jeśli chodzi o skrajne przypadki niewystarczającej ilości znaków, można dodać "abcd", ale wolałbym, aby było to czystsze, po prostu w osobnej linii po fakcie: output_string = (output_string + "abcd")[0..3] if output_string.length < 4. Jest to znacznie czytelniejsze i działa (niekonsekwentnie) lepiej, jeśli jest to naprawdę rzadki przypadek.

+1

Niezły, Andrew. Możesz również napisać 'str.gsub (/ [^ A-Z] + ([A-Z]) /, '\ 1') [0,4] .upcase'. –

+0

To jest naprawdę bardzo miłe! Dziękuję Ci! – linkyndy

3

Oto rozwiązanie:

((str.scan(/[A-Z]/)[0..-2] + str.scan(/[A-Z][^A-Z]*$/)).join + "abcd")[0, 4].upcase 

I to jest tutaj z opinii:

(
    (
    str.scan(/[A-Z]/)[0..-2] + # All but the last capital letter 
    str.scan(/[A-Z]?[^A-Z]*$/) # The last capital letter, if any, plus trailing lowercase letters 
).join + 
    "abcd" 
)[0, 4]. # Take the first 4 chars, 4 capitals if we have them, then trailing lowercase if we have those, then the "abcd" filler 
upcase # upcase any trailing lowercase letters we included 
+0

Wygląda interesująco. Czy istnieje sposób na użycie pojedynczego wyrażenia regularnego? Nie jestem pewien, w jaki sposób można napisać wyrażenie regularne "wszystkie wystąpienia, ale ostatnie". – linkyndy

+0

Możesz dopasować nieznaną liczbę wielkich liter, ewentualnie rozdzielonych małymi literami w jednym wyrażeniu regularnym, ale nie ma sposobu na przechwycenie tylko wielkich liter. –

1

Oto dwie metody.

# 1 Zastosowanie String#gsub z regex, następnie String#upcase i String#[]

R =/
    [a-z]   # match a lower case letter 
    (?=[a-z]*[A-Z]) # match >= 0 lower case letters followed by an upper case letter 
        # in a positive lookahead 
    /x    # free-spacing regex definition mode 

def get_caps(str, n) 
    str.gsub(R,"").upcase[0,4] 
end 

get_caps("ThisIsMyString", 4)   #=> "TIMS" 
get_caps("ThisIsOneVeryLongString", 4) #=> "TIOV" 
get_caps("MyString", 4)    #=> "MSTR" 
get_caps("abcde", 4)     #=> "ABCD" 
get_caps("", 4)      #=> "" 
get_caps("AbcdefGh", 4)    #=> "AGH" 

# 2 Określić indeks ostatniej litery, a następnie zbudować ciąg

def get_caps(str, n) 
    idx = str.rindex(/[A-Z]/) 
    return str[0,4].upcase if idx.nil? 
    str.each_char.with_index.with_object('') { |(c,i),s| 
    s << c.upcase if (s.size < n && (i > idx || c == c.upcase)) } 
end 

get_caps("ThisIsMyString", 4)   #=> "TIMS" 
get_caps("ThisIsOneVeryLongString", 4) #=> "TIOV" 
get_caps("MyString", 4)    #=> "MSTR" 
get_caps("abcde", 4)     #=> "ABCD" 
get_caps("", 4)      #=> "" 
get_caps("AbcdefGh", 4)    #=> "AGH" 

Jeśli chcesz zwrócić nil, jeśli zwracany ciąg zawiera mniej niż n znaków, dodaj to sprawdzanie do metod.

Powiązane problemy