Discussion:
jak odzielić ulicę od numeru domu i lokalu
(Wiadomość utworzona zbyt dawno temu. Odpowiedź niemożliwa.)
karpusx
2003-10-17 13:30:02 UTC
Permalink
Witam!
No drodzy państwo, pasy proszę zapinać, bo takiego tematu tu jeszcze nie było.
Problem nie jest związany bezpośrednio z samą Javą, ale wiem, że na tym forum
występują różnoracy giganci programistyczni, po za tym istnieje do Javy sporo
ciekawych klas.
Do dzieła:
W jednym stringu jest nazwa ulicy, numer domu i lokalu. Należy stworzyć
algorytm, który rozwali to na poszczególne wielkości: ulicę, nr domu i nr
lokalu, uwzględniając przy tym rozmaite przypadki.
Problem urodził się przy obróbce np. 5 mln adresów: tu się znajduje poprostu
wszytsko, np:
"Dworcowa 76/ - genia dopisz coś tutaj, ale zrób to do 10ego"
Może sieci neuronowe?
Pozdrawiam.
--
Wysłano z serwisu OnetNiusy: http://niusy.onet.pl
Jan Klonowski
2003-10-17 14:38:25 UTC
Permalink
Witam,
Post by karpusx
Może sieci neuronowe?
Ja to bym zastosował oprogramowanie z NASA :))
A tak na poważnie, spróbuj javacc parser generator. To jest wg mnie lepsze
niż LEX połączony z YACCem. Przy czym prawdopodobnie i tak będzie trzeba
odnajdować błędne przypadki i je "ręcznie" rozpatrywać.
Jasio
p***@gazeta.SKASUJ.TO.pl
2003-10-18 16:52:06 UTC
Permalink
Post by karpusx
W jednym stringu jest nazwa ulicy, numer domu i lokalu. Należy stworzyć
algorytm, który rozwali to na poszczególne wielkoœci: ulicę, nr domu i nr
lokalu, uwzględniajšc przy tym rozmaite przypadki.
Problem urodził się przy obróbce np. 5 mln adresów: tu się znajduje poprostu
"Dworcowa 76/ - genia dopisz coœ tutaj, ale zrób to do 10ego"
Może sieci neuronowe?
nie wiem czy to będzie jakaœ pomoc i czy o to ci chodziło ,ale napisałem tu
kawałek kodziku nie jest to rozwišzanie problemu ale można to sobie
przemyœleć.

oczywiœcie funkcja skierowana jest już do pojedynczego tokena z adresu ulicy
tj: numeru drzwi

Sorry że użyłem tutaj tylko klasy string ale w tej chwili nie mam dojœcia do
dokumentacji StringTokenizera wiem że ma on funkcje znajdowania liczby.

Baze słów oczywiœcie lepiej umieœcić w oddzielnym pliku a nie tablicy 'słowa'


-------------------------------------------------------------

String s= "coœt10am"
String[] słowa={baza słów sensownych
np: "mieszkanie", "mieszkania", "drzwi", "m", "m." itp.}
String nrdrzwi = null;
String banialuki = null;

int a;
int b;
int c= -1;
int d= -1;

/**
czy string zawiera liczbę
*/

while(a < 10){

if((b=s.indexOf(String.valueOf(a) ) ) < -1);
a++;
else{
c=b;
a=10;
b=-1;
}
}

a=0;

while(a < 10){

if((b=s.lastIndexOf(String.valueOf(a))) < -1);
a++;
else{
d=b;
a=10;
b=-1;
}
}


if(c > -1){

nrdrzwi = s.substring(c,d);

/**
czy jest to liczba sensowna bo może być- nrdrzwi= "1edzie9"
bo jerzeli to ma być numer drzwi to nikt nie będzie pisał
m 10 coœtam 9
jest to bezsensu a co najmniejej podejrzane
*/

try{
Integer.parseInt(nrdrzwi);
}
catch(NFE e){
return null;
}

}


/**
jeżeli jest to liczba to czy jej granice sš sensowne
nr drzwi 10000 raczej nie isnieje :-)
*/

if(s.length() == nrdrzwi.length()&& f.length() < 5)

return nrdrzwi; //mamy właœciwy numer ;-)

/**
badamy co tam jeszcze jest porównujšc to z bazš możliwych 'słów' które mogš
tam
się znaleŸć jeżeli sš sensowne to wyrzucamy numer
*/

else{
banialuki=s.substring(0,c);
a = 0;

while(słowa.length < a){
if(banialuki.equals(słowa[a]) )
return nrdrzwi; // mamy numer
a++;
}

}

return null;


pozdrowienia.
--
Wysłano z serwisu Usenet w portalu Gazeta.pl -> http://www.gazeta.pl/usenet/
nowek
2003-10-18 16:54:04 UTC
Permalink
Post by karpusx
W jednym stringu jest nazwa ulicy, numer domu i lokalu. Należy stworzyć
algorytm, który rozwali to na poszczególne wielkoœci: ulicę, nr domu i nr
lokalu, uwzględniajšc przy tym rozmaite przypadki.
Problem urodził się przy obróbce np. 5 mln adresów: tu się znajduje poprostu
"Dworcowa 76/ - genia dopisz coœ tutaj, ale zrób to do 10ego"
Może sieci neuronowe?
nie wiem czy to będzie jakaœ pomoc i czy o to ci chodziło ,ale napisałem tu
kawałek kodziku nie jest to rozwišzanie problemu ale można to sobie
przemyœleć.

oczywiœcie funkcja skierowana jest już do pojedynczego tokena z adresu ulicy
tj: numeru drzwi

Sorry że użyłem tutaj tylko klasy string ale w tej chwili nie mam dojœcia do
dokumentacji StringTokenizera wiem że ma on funkcje znajdowania liczby.

Baze słów oczywiœcie lepiej umieœcić w oddzielnym pliku a nie tablicy 'słowa'


-------------------------------------------------------------

String s= "coœt10am"
String[] słowa={baza słów sensownych
np: "mieszkanie", "mieszkania", "drzwi", "m", "m." itp.}
String nrdrzwi = null;
String banialuki = null;

int a;
int b;
int c= -1;
int d= -1;

/**
czy string zawiera liczbę
*/

while(a < 10){

if((b=s.indexOf(String.valueOf(a) ) ) < -1);
a++;
else{
c=b;
a=10;
b=-1;
}
}

a=0;

while(a < 10){

if((b=s.lastIndexOf(String.valueOf(a))) < -1);
a++;
else{
d=b;
a=10;
b=-1;
}
}


if(c > -1){

nrdrzwi = s.substring(c,d);

/**
czy jest to liczba sensowna bo może być- nrdrzwi= "1edzie9"
bo jerzeli to ma być numer drzwi to nikt nie będzie pisał
m 10 coœtam 9
jest to bezsensu a co najmniejej podejrzane
*/

try{
Integer.parseInt(nrdrzwi);
}
catch(NFE e){
return null;
}

}


/**
jeżeli jest to liczba to czy jej granice sš sensowne
nr drzwi 10000 raczej nie isnieje :-)
*/

if(s.length() == nrdrzwi.length()&& f.length() < 5)

return nrdrzwi; //mamy właœciwy numer ;-)

/**
badamy co tam jeszcze jest porównujšc to z bazš możliwych 'słów' które mogš
tam
się znaleŸć jeżeli sš sensowne to wyrzucamy numer
*/

else{
banialuki=s.substring(0,c);
a = 0;

while(słowa.length < a){
if(banialuki.equals(słowa[a]) )
return nrdrzwi; // mamy numer
a++;
}

}

return null;


pozdrowienia.
--
Wysłano z serwisu Usenet w portalu Gazeta.pl -> http://www.gazeta.pl/usenet/
nowek
2003-10-18 17:10:44 UTC
Permalink
Post by karpusx
Post by karpusx
W jednym stringu jest nazwa ulicy, numer domu i lokalu. Należy stworzyć
algorytm, który rozwali to na poszczególne wielkoœci: ulicę, nr domu i nr
lokalu, uwzględniajšc przy tym rozmaite przypadki.
Problem urodził się przy obróbce np. 5 mln adresów: tu się znajduje
poprostu
Post by karpusx
"Dworcowa 76/ - genia dopisz coœ tutaj, ale zrób to do 10ego"
Może sieci neuronowe?
nie wiem czy to będzie jakaœ pomoc i czy o to ci chodziło ,ale napisałem tu
kawałek kodziku nie jest to rozwišzanie problemu ale można to sobie
przemyœleć.
oczywiœcie funkcja skierowana jest już do pojedynczego tokena z adresu ulicy
tj: numeru drzwi
Sorry że użyłem tutaj tylko klasy string ale w tej chwili nie mam dojœcia do
dokumentacji StringTokenizera wiem że ma on funkcje znajdowania liczby.
Baze słów oczywiœcie lepiej umieœcić w oddzielnym pliku a nie tablicy 'słowa'
-------------------------------------------------------------
String s= "coœt10am"
String[] słowa={baza słów sensownych
np: "mieszkanie", "mieszkania", "drzwi", "m", "m." itp.}
String nrdrzwi = null;
String banialuki = null;
int a;
int b;
int c= -1;
int d= -1;
/**
czy string zawiera liczbę
*/
while(a < 10){
if((b=s.indexOf(String.valueOf(a) ) ) < 0); //tu był błąd
a++;
else{
c=b;
a=10;
b=-1;
}
}
a=0;
while(a < 10){
if((b=s.lastIndexOf(String.valueOf(a))) < 0); // tu też ;-)
a++;
else{
d=b;
a=10;
b=-1;
}
}
if(c > -1){
nrdrzwi = s.substring(c,d);
/**
czy jest to liczba sensowna bo może być- nrdrzwi= "1edzie9"
bo jerzeli to ma być numer drzwi to nikt nie będzie pisał
m 10 coœtam 9
jest to bezsensu a co najmniejej podejrzane
*/
try{
Integer.parseInt(nrdrzwi);
}
catch(NFE e){
return null;
}
}
/**
jeżeli jest to liczba to czy jej granice sš sensowne
nr drzwi 10000 raczej nie isnieje :-)
*/
if(s.length() == nrdrzwi.length()&& f.length() < 5)
return nrdrzwi; //mamy właœciwy numer ;-)
/**
badamy co tam jeszcze jest porównujšc to z bazš możliwych 'słów' które mogš
tam
się znaleŸć jeżeli sš sensowne to wyrzucamy numer
*/
else{
banialuki=s.substring(0,c);
a = 0;
while(słowa.length < a){
if(banialuki.equals(słowa[a]) )
return nrdrzwi; // mamy numer
a++;
}
}
return null;
pozdrowienia.
--
Wysłano z serwisu Usenet w portalu Gazeta.pl -> http://www.gazeta.pl/usenet/
Filip Sielimowicz
2003-10-18 21:15:58 UTC
Permalink
Wg mnie do takich rzeczy bardzo dobrze nadają się wyrażenia
regularne. Właśnie pracuję nad identycznym problemem.
(czy ty przypadkiem nie pracujesz w grupie analitycznej
w mojej firmie ? :))))
Zobacz pakiet java.util.regex.*. Jutro będę w pracy to podam
więcej szczegółow, teraz powiem, jak u nas wyglądają
przykładowe adresy:

Sobieskiego 2/4
Sobieskiego 2B/4
Sobiesk. 2/4
Sobieskiego2B/4
Sobieskiego 2 M 4
Sobieskiego 2 M. 4
Sobieskiego 2M.4
Sobiesk.2M4
Sobieskiego 2
Sobieskiego2
Sobieskiego 2B
Sobieskiego2B
ul. 1000-lecia 2
ul. 1000-lecia 2/4
ul. ...
i podobne

Zdarzają się też i takie:
Sobieskiego 2/3/1
Sobieskiego 4/
Sobieskiego 2\4
itp.
Te z drugiej grupy po prostu uznaję za nieprawidłowe i się nie szczypię
(trudno się mówi, wszystkiego i tak nie zgadniemy. Wrzucamy wtedy wszystko
w ulicę, numery ustawiamy na 0, co oznacza u nas "Brak Danych").
Te z pierwszej grupy wszystkie udaje mi się przerobić prawidłowo.
Zasady, które przyjąłem są mniej więcej takie:
1. Dla bezpieczeństwa przyjmij, że trzy ostatnie litery ulicy nie są
cyframi (ani znakami pustymi).
2. Jako separator nr domu i nru lokalu dopuść '/', 'M' lub 'M.'
3. Jako numer domu dopuść dowolną liczbę + opcjonalnie jedną literę
4. Numer lokalu jest opcjonalny i składa się tylko z cyfr.
5. Za adresem nie może się już nic znajdować (jedynie znaki puste).

Wszystkie te zasady udaje się zawrzeć w jednym wyrażeniu regularnym
i kodu jest w związku z tym naprawdę niewiele.
Jutro podam przykład (nie podpowiem jednak wszystkiego, żeby się
mie nikt nie mógł czepiać, że takie cudowne tajemnice
wyjawiam publicznie... ).
Filip Sielimowicz
2003-10-19 12:53:17 UTC
Permalink
Post by Filip Sielimowicz
Te z drugiej grupy po prostu uznaję za nieprawidłowe i się nie szczypię
(trudno się mówi, wszystkiego i tak nie zgadniemy. Wrzucamy wtedy wszystko
w ulicę, numery ustawiamy na 0, co oznacza u nas "Brak Danych").
Te z pierwszej grupy wszystkie udaje mi się przerobić prawidłowo.
1. Dla bezpieczeństwa przyjmij, że trzy ostatnie litery ulicy nie są
cyframi (ani znakami pustymi).
2. Jako separator nr domu i nru lokalu dopuść '/', 'M' lub 'M.'
3. Jako numer domu dopuść dowolną liczbę + opcjonalnie jedną literę
4. Numer lokalu jest opcjonalny i składa się tylko z cyfr.
5. Za adresem nie może się już nic znajdować (jedynie znaki puste).
Wszystkie te zasady udaje się zawrzeć w jednym wyrażeniu regularnym
i kodu jest w związku z tym naprawdę niewiele.
Jutro podam przykład (nie podpowiem jednak wszystkiego, żeby się
mie nikt nie mógł czepiać, że takie cudowne tajemnice
wyjawiam publicznie... ).
Powyższe wyrażenie regularne wygląda tak:
([^/]*[^0-9/\s]{3,})[\s]*([0-9]+[0-9a-zA-Z]?)(\s*(/|M|M.)\\s*([0-9]+))?$


A kod funkcji z niego korzystającej tak:

//Wzorzec wydobywający cyfry kodu pocztowego
private static String regexNumeryDomu =
"([^/]*[^0-9/\\s]{3,})[\\s]*([0-9]+[0-9a-zA-Z]?)(\\s*(/|M|M.)\\s*([0-9]+))?$";
private static Pattern patNumeryDomu = Pattern.compile(regexNumeryDomu);

/** Funkcja stara się wydobyć numer domu i numer mieszkania (opcjonalnie)
* @return Zwraca trzyelementową tablicę stringów, w pierwszym elemencie jest
nawa ulicy, w drugim numer domu, w trzecim nr mieszkania
* Jeśli nie uda się dopasować do wzorca, to wszystko pozostaje w numerze ulicy.
*/
static String[] wyodrebnijNumeryDomu(String ulica) {
String[] retNumeryDomu=new
String[]{BRAK_DANYCH_ADRES__ULICA,BRAK_DANYCH_ADRES__NR_DOMU,BRAK_DANYCH_ADRES__NR_LO
KALU};
if (ulica!=null) ulica=ulica.trim();
if (ulica!=null) {
Matcher m = patNumeryDomu.matcher(ulica);
if (m.matches()) {
//Znaleźliśmy co trzeba.
retNumeryDomu[0]=m.group(1);
retNumeryDomu[1]=m.group(2);
retNumeryDomu[2]=m.group(5);
} else {
//Nie udało się dopasować, są jakieś krzaki. Przepisujemy całe pole
ulica i zapominamy o sprawie.
if (!ulica.equals("")) {
retNumeryDomu[0]=ulica;
}
}
}
return retNumeryDomu;
}

Mankamenty:
to wyrażenie nie chwyci adresów, w których:
1. Litera w numerze domu jest oddzielona spacją od numeru
2. W numerze lokalu występuje litera (a zdarza się, jak się okazuje)
3. Nie wspomnę już nawet o np. takim adresie:
ul. Dywizjonu 303 5BM.28

:)
Pozostawiam to do własnych rozważań. Mi się udało :)
james22
2003-10-19 18:56:25 UTC
Permalink
stawiam na java.util.regexp.*

Loading...