stringa di formato (codice postale) in rubino
-
25-09-2019 - |
Domanda
Devo riformattare un elenco di codici postali del Regno Unito e ho iniziato con quanto segue per eliminare gli spazi bianchi e utilizzare le maiuscole:
postcode.upcase.gsub(/\s/,'')
Ora devo modificare il codice postale in modo che il nuovo codice postale sia in un formato che corrisponda alla seguente espressione regolare:
^([A-PR-UWYZ0-9][A-HK-Y0-9][AEHMNPRTVXY0-9]?[ABEHMNPRVWXY0-9]? {1,2}[0-9][ABD-HJLN-UW-Z]{2}|GIR 0AA)$
Sarei grato di qualsiasi assistenza.
Soluzione
Se questo standard doc bisogna crederci (e Wikipedia concorda), la formattazione di un codice postale valido per l'output è semplice:gli ultimi tre personaggi sono la seconda parte, tutto quello che precede è la prima parte!
Quindi, supponendo che tu abbia un codice postale valido, senza spazio preincorporato, ti basta
def format_post_code(pc)
pc.strip.sub(/([A-Z0-9]+)([A-Z0-9]{3})/, '\1 \2')
end
Se vuoi convalidare prima un codice postale di input, la regex che hai fornito sembra un buon punto di partenza.Forse qualcosa del genere?
NORMAL_POSTCODE_RE = /^([A-PR-UWYZ][A-HK-Y0-9][A-HJKS-UW0-9]?[A-HJKS-UW0-9]?)\s*([0-9][ABD-HJLN-UW-Z]{2})$/i
GIROBANK_POSTCODE_RE = /^GIR\s*0AA$/i
def format_post_code(pc)
return pc.strip.upcase.sub(NORMAL_POSTCODE_RE, '\1 \2') if pc =~ NORMAL_POSTCODE_RE
return 'GIR 0AA' if pc =~ GIROBANK_POSTCODE_RE
end
Da notare che ho rimosso la parte '0-9' del primo carattere, che risulta non necessaria secondo le fonti che ho citato.Ho anche modificato i set alpha in modo che corrispondano al primo documento citato.Non è ancora perfetto:un codice del formato "AAA ANN" convalida, ad esempio, e penso che probabilmente sia necessaria una RE più complessa.
Penso che questo potrebbe coprirlo (costruito in più fasi per un fissaggio più semplice!)
A1 = "[A-PR-UWYZ]"
A2 = "[A-HK-Y]"
A34 = "[A-HJKS-UW]" # assume rule for alpha in fourth char is same as for third
A5 = "[ABD-HJLN-UW-Z]"
N = "[0-9]"
AANN = A1 + A2 + N + N # the six possible first-part combos
AANA = A1 + A2 + N + A34
ANA = A1 + N + A34
ANN = A1 + N + N
AAN = A1 + A2 + N
AN = A1 + N
PART_ONE = [AANN, AANA, ANA, ANN, AAN, AN].join('|')
PART_TWO = N + A5 + A5
NORMAL_POSTCODE_RE = Regexp.new("^(#{PART_ONE})[ ]*(#{PART_TWO})$", Regexp::IGNORECASE)
Altri suggerimenti
Regno Unito NPA non sono coerenti, ma sono finite -. Si potrebbe essere meglio con un look-up table
Riformatta o pattern match? Ho il sospetto che questi, pur upcasing in primo luogo è una buona idea.
Prima di procedere però vorrei sottolineare che si sta stripping spazi ma la tua espressione regolare contiene "{1,2}", che è "uno o due di spazio caratteri". Come si è già messo a nudo gli spazi bianchi hai già causato tutto a fallire la partita.
Dato un codice postale come input possiamo verificare se abbina la regex usando = ~
Qui creiamo alcuni codici di esempio sul post (tratti dalla wikipedia pagina ), e il test ognuno contro la regex:
post_codes = ["M1 1AA", "M60 1NW", "CR2 6XH", "DN55 1PT", "W1A 1HQ", "EC1A 1BB", "bad one", "cc93h29r2"]
r = /^([A-PR-UWYZ0-9][A-HK-Y0-9][AEHMNPRTVXY0-9]?[ABEHMNPRVWXY0-9]? {1,2}[0-9][ABD-HJLN-UW-Z]{2}|GIR 0AA)$/
post_codes.each do |pc|
# pc =~ r will return something true if we have a match (specifically the integer of first match position)
# We use !! to display it as true|false
puts "#{pc}: #{!!(pc =~ r)}"
end
M1 1AA: true
M60 1NW: true
CR2 6XH: true
DN55 1PT: true
W1A 1HQ: true
EC1A 1BB: true
bad one: false
cc93h29r2: false