2016-04-29 30 views
5

Ho una stringa con custodia di cammello, ad esempio: JustAString.Far corrispondere le lettere maiuscole e compilare con lettere successive fino a quando la lunghezza della stringa specifica

Vorrei formare stringhe di lunghezza seguendo queste regole:

  • afferrare tutte le lettere maiuscole;
  • se più di 4 lettere maiuscole, mantenere solo i primi 4;
  • se meno di 4 lettere maiuscole, capitalizzare e aggiungere lettere che seguono la lettera maiuscola scorso, finché la lunghezza diventa 4.

Qui ci sono i 3 casi che possono accadere:

  • ThisIsMyString produrrà TIMS (maiuscolo);
  • ThisIsOneVeryLongString produrrà TIOV (prime 4 capitali);
  • MyString produrrà MSTR (maiuscolo + tr in maiuscolo).

sono riuscito a risolvere i primi due casi con questo frammento:

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

Tuttavia, io non sono del tutto sicuro come posso meglio modificare il frammento di codice per gestire l'ultimo caso anche (o anche provare qualcosa di diverso).

P.S .: La stringa è garantita con almeno una maiuscola e 4 caratteri. Tuttavia, se teoricamente manca un capitale, i primi 4 caratteri dovrebbero essere presi in considerazione. Se non ci sono 4 caratteri, i caratteri mancanti possono essere compilati con i primi caratteri dell'alfabeto (abcd). Ma, come accennato, questi due casi limite non si verificano normalmente.

risposta

4

sostituire qualsiasi carattere (s) che precede una capitale con niente, poi prendete i primi 4 caratteri e upcase :

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

Questo gestisce non CAPI anche i tals. Per quanto riguarda il caso limite di non abbastanza caratteri, è possibile aggiungere "abcd", ma lo troverei più pulito solo per farlo in una riga separata dopo il fatto: output_string = (output_string + "abcd")[0..3] if output_string.length < 4. Questo si legge molto più pulito e si comporta (se possibile in modo irrilevante) meglio se questo è davvero un caso raro.

+1

Bello, Andrew. Puoi anche scrivere 'str.gsub (/ [^ A-Z] + ([A-Z]) /, '\ 1') [0,4] .upcase'. –

+0

Questo è davvero molto bello! Grazie! – linkyndy

3

Ecco una soluzione:

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

e qui è con i commenti:

(
    (
    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

Sembra interessante. C'è un modo per usare una singola regex? Non sono sicuro di come si possa scrivere un regex "tutte le occorrenze tranne l'ultima". – linkyndy

+0

È possibile associare un numero sconosciuto di lettere maiuscole eventualmente separate da lettere minuscole in una singola espressione regolare, ma non è possibile acquisire solo le maiuscole. –

1

Ecco due metodi.

# 1 Usare String#gsub con una regex, seguito da String#upcase e 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 Determinare l'indice dell'ultimo lettera maiuscola e poi costruire la stringa

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" 

Se si desidera restituire nil se la stringa restituita contiene meno di n caratteri, aggiungi questo controllo ai metodi.