2013-04-21 14 views
6

Sto elaborando gli indirizzi nel rispettivo formato di campo per il database. Posso ottenere il numero civico e il tipo di strada, ma sto cercando di determinare il metodo migliore per ottenere la strada senza numero e l'ultima parola. Un indirizzo di serie ricevuto sarebbe:Analizzare gli indirizzi stradali in Ruby

res[:address] = '7707 Foo Bar Blvd' 

A partire da ora posso analizzare il seguente:

house = res[:address].gsub(/\D/, '') 
    street_type = res[:address].split(/\s+/).last 

La mia prima sfida è come ottenere 'Foo Bar'. Nota il nome della via potrebbe essere una, due o tre parole. Sto lottando per trovare una soluzione di espressione a una riga per questo in Ruby.

La mia seconda domanda è come migliorare il codice "casa" per gestire i numeri civici che hanno un alfa alla fine. Ad esempio, "7707B".

Infine, se è possibile fare riferimento a un buon cheat sheet con esempi per queste espressioni, sarebbe utile.

+4

Semplice, non farlo! o chiedere i campi individualmente o memorizzarli nel loro complesso. l'analisi di questo non sarà mai accurata al 100% perché la quantità di variazione è maggiore di quanto tu possa immaginare. Se si desidera un campo numero civico (che non si dovrebbe) avere un campo numero_casa nel modulo. – drhenner

+2

BTW: esiste un'API con USPS. https://www.usps.com/business/web-tools-apis/welcome.htm possono verificare il tuo indirizzo e possibilmente fornirti informazioni dettagliate migliori. – drhenner

+0

Il database delle proprietà di base che sto modificando ha i campi separati in questo modo, motivo per cui il campo casa e il tipo di strada. Ho anche un indirizzo completo. Sto facendo questo per coerenza nei dati dove possibile –

risposta

9

Suggerirei di utilizzare una libreria per questo se possibile, poiché l'analisi dell'indirizzo può essere difficile. Controlla la Indirizzo rubino gemma, il che rende questo facile:

require 'Indirizzo' 
address = Indirizzo::Address.new("7707 Foo Bar Blvd") 
address.number 
=> "7707" 
address.street 
=> ["foo bar blvd", "foo bar boulevard"] 

Anche se non utilizza la libreria di Indirizzo per sé, la lettura attraverso il suo codice sorgente è probabilmente molto utile per vedere come hanno risolto il problema. Ad esempio, è finemente sintonizzato espressioni regolari per abbinare diverse parti di un indirizzo:

Match = { 
    # FIXME: shouldn't have to anchor :number and :zip at start/end 
    :number => /^(\d+\W|[a-z]+)?(\d+)([a-z]?)\b/io, 
    :street => /(?:\b(?:\d+\w*|[a-z'-]+)\s*)+/io, 
    :city  => /(?:\b[a-z][a-z'-]+\s*)+/io, 
    :state => State.regexp, 
    :zip  => /\b(\d{5})(?:-(\d{4}))?\b/o, 
    :at  => /\s(at|@|and|&)\s/io, 
    :po_box => /\b[P|p]*(OST|ost)*\.*\s*[O|o|0]*(ffice|FFICE)*\.*\s*[B|b][O|o|0][X|x]\b/ 
} 

Questi file dal suo codice sorgente può dare più specifiche:

(ma vorrei anche in generale d'accordo con commento di @ drhenner che, al fine di rendere questo più facile su te stesso, probabilmente si potrebbe semplicemente accettare questi ingressi dati in campi separati)

Edit:. Per dare una risposta più specifica su come rimuovere il suffisso strada (ad esempio, "Blvd"), è possibile utilizzare le costanti di espressioni regolari di dell'Indirizzo (come ad esempio Suffix_Type da constants.rb) in questo modo:

address = Indirizzo::Address.new("7707 Foo Bar Blvd", :expand_streets => false) 
address.street.map {|street| street.gsub(Indirizzo::Suffix_Type.regexp, '').strip } 
=> ["foo bar"] 

(Notate che ho anche passato :expand_streets => false al inizializzatore, per evitare di avere entrambi "Blvd "e" Boulevard "si sono espanse, dal momento che stiamo comunque scartando il suffisso.)

+1

Stuart Ho guardato questa gemma ma non ho visto dove si è occupato di ottenere l'indirizzo senza il tipo di strada. Ancora una volta si tratta solo di cercare di abbinare i campi dati. Ho anche un indirizzo completo per rendere le cose più facili. –

+0

L'indirizzo non sembra avere un metodo integrato per separare la strada _name_ dal suo suffisso (ad esempio "Blvd"). Ma ha quei suffissi come costanti (come 'Indirizzo :: Suffix_Type' da' constants.rb'. Potresti usarli per analizzare i suffissi.Ho aggiornato la mia risposta con un suggerimento su come farlo –

+0

Stuart lo darò io ci provo ma ci vorrà un po 'di tempo per controllare la gemma oltre quello che ho fatto in precedenza. Sembra che questo potrebbe funzionare e forse cambierò solo il mio codice precedente. ora. Grazie –

1

Si potrebbe forse usare qualcosa come:

^\S+ (.+?) \S+$

\S corrisponde a qualsiasi carattere di spazio non bianco

^ corrisponde all'inizio della stringa

$ corrisponde alla fine della stringa

E (.+?) cattura qualsiasi cosa tra i due.

2

Si può giocare a tira e molla con i gruppi di cattura denominati in una regex

matches = res[:address].match(/^(?<number>\S*)\s+(?<name>.*)\s+(?<type>.*)$/) 
number = matches[:number] 
house = matches[:name] 
street_type = matches[:type] 

o se si voleva la vostra regex per essere un po 'più precisa con il tipo si potrebbe sostituire (?<type>.*) con (?<type>(Blvd|Ave|Rd|St)) e aggiungi tutte le diverse opzioni che desideri

0

Controlla attentamente il set di dati per assicurarti che il problema non sia già stato gestito per te.

Ho trascorso un bel po 'di tempo prima di creare una tassonomia del nome della strada che terminava, usando regexp condizionali per provare a strappare il numero civico dalle stringhe di indirizzo completo e tutto e si è scoperto che la tabella degli attributi per i miei shapefile aveva già segmentato questi componenti.

Prima di procedere con il processo di analisi delle stringhe di indirizzo, che è sempre un po 'complicato a causa delle inevitabili strane variazioni (alcuni indirizzi di pacchi sono per pacchi senza sbocco sul mare e hanno indirizzi strani, ecc.), Assicurati che il tuo set di dati non l'ha già fatto per te !!!


ma se non lo fai, esegue attraverso le stringhe di indirizzo, address.split(" ") crea una serie di 'parole'. Nella maggior parte dei casi la prima "parola" è il numero civico. Questo ha funzionato per circa il 95% dei miei indirizzi. (NOTA: il mio: stringhe di indirizzo non contengono città, provincia, stato, CAP, erano solo gli indirizzi locali)

Mi sono imbattuto nell'intera popolazione di indirizzi e prelevato l'ultima "parola" da ogni indirizzo & esaminato array & eliminava "parole" che non erano "Lane", "Road", "Rd" o qualsiasi altra cosa. Da questo elenco di terminazioni di indirizzo che ho creato questo enorme oggetto corrispondente regexp

streetnm_endings = street_endings.map {|s| /#{s}/ } 
endings_matches = Regexp.union(street_endings) 

Ho corso attraverso ogni stringa di indirizzo, shift -ing il primo membro di matrice perché, ancora una volta che è stato il numero quasi sempre via. E poi gsub'd le terminazioni di strada per ottenere quello che dovrebbe essere il numero nome della strada sans strada o di strada terminazioni nome, che i database non piace in generale:

parcels.each do |p| 
    remainder = p.address.split(" ") 
    p.streetnum = remainder.shift 
    p.streetname = remainder.join(" ").gsub(endings_matches, "") 
    p.save 
end 

E non sempre funziona, ma ha funzionato la maggior parte di il tempo.

0

Attualmente passo solo tutto ciò che mi è stato dato su googlemaps e chiedo loro di restituire un indirizzo stradale formattato che è molto facile da analizzare.

function addressReview(addressInput) { 
geocoder = new google.maps.Geocoder(); 
var latlng = new google.maps.LatLng(-34.397, 150.644); 
geocoder.geocode({ 'address': addressInput}, function(results, status) { 
if (status == google.maps.GeocoderStatus.OK) { 
    if (results[0]) { 
    var addr = results[0].formatted_address; 
    var latTi = results[0].geometry.location.lat(); 
    var lonGi = results[0].geometry.location.lng(); 
    $.post('/welcome/gcode',{ add: addr , la: latTi , lo: lonGi }); 
    $('#cust_addy').val(addr); 
    } else { 
    $('#cust_addy').attr("placeholder",'Cannnot determine location'); 
    } 
} else { 
    $('#cust_addy').attr("placeholder",'Cannnot determine location'); 
} 
}); 
} 

Dopo, l'ho diviso in rubino. con .split (',') e .split ('')

Problemi correlati