Skip to content

Commit 1b6eea1

Browse files
committed
feat(streets_with_no_suffix): improved support for streets with no suffix, such as "broadway"
1 parent 72d6463 commit 1b6eea1

14 files changed

+209
-2
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
const Classification = require('./Classification')
2+
3+
class StreetProperNameClassification extends Classification {
4+
constructor (confidence, meta) {
5+
super(confidence, meta)
6+
this.label = 'street_proper_name'
7+
}
8+
}
9+
10+
module.exports = StreetProperNameClassification
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
const Classification = require('./StreetProperNameClassification')
2+
3+
module.exports.tests = {}
4+
5+
module.exports.tests.constructor = (test) => {
6+
test('constructor', (t) => {
7+
let c = new Classification()
8+
t.false(c.public)
9+
t.equals(c.label, 'street_proper_name')
10+
t.equals(c.confidence, 1.0)
11+
t.deepEqual(c.meta, {})
12+
t.end()
13+
})
14+
}
15+
16+
module.exports.all = (tape, common) => {
17+
function test (name, testFunction) {
18+
return tape(`StreetProperNameClassification: ${name}`, testFunction)
19+
}
20+
21+
for (var testCase in module.exports.tests) {
22+
module.exports.tests[testCase](test, common)
23+
}
24+
}

classifier/CompositeClassifier.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,9 @@ class CompositeClassifier extends SectionClassifier {
106106
// find phrases which equal the composites
107107
let superPhrases = []
108108
composites.forEach(c => {
109-
let start = c[0].start
110-
let end = c[c.length - 1].end
109+
var carr = Array.isArray(c) ? c : [c] // cast to array
110+
let start = carr[0].start
111+
let end = carr[carr.length - 1].end
111112
superPhrases = superPhrases.concat(phrases.filter(p => p.start === start && p.end === end))
112113
})
113114

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
const WordClassifier = require('./super/WordClassifier')
2+
const StreetProperNameClassification = require('../classification/StreetProperNameClassification')
3+
4+
/**
5+
Special handling of streets with no suffix
6+
7+
see: https://github.com/pelias/parser/issues/140
8+
**/
9+
10+
class StreetProperNameClassifier extends WordClassifier {
11+
setup () {
12+
this.index = {
13+
'broadway': true,
14+
'esplanade': true
15+
}
16+
}
17+
18+
each (span) {
19+
// skip spans which contain numbers
20+
if (span.contains.numerals) { return }
21+
22+
// classify tokens in the index as 'street_proper_name'
23+
if (this.index[span.norm] === true) {
24+
span.classify(new StreetProperNameClassification(0.7))
25+
}
26+
}
27+
}
28+
29+
module.exports = StreetProperNameClassifier
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
const StreetProperNameClassifier = require('./StreetProperNameClassifier')
2+
const StreetProperNameClassification = require('../classification/StreetProperNameClassification')
3+
const Span = require('../tokenization/Span')
4+
const classifier = new StreetProperNameClassifier()
5+
6+
module.exports.tests = {}
7+
8+
function classify (body) {
9+
let s = new Span(body)
10+
classifier.each(s, null, 1)
11+
return s
12+
}
13+
14+
module.exports.tests.contains_numerals = (test) => {
15+
test('contains numerals: honours contains.numerals boolean', (t) => {
16+
let s = new Span('example')
17+
s.contains.numerals = true
18+
classifier.each(s, null, 1)
19+
t.deepEqual(s.classifications, {})
20+
t.end()
21+
})
22+
}
23+
24+
module.exports.tests.street_proper_names = (test) => {
25+
let valid = [
26+
'broadway',
27+
'esplanade'
28+
]
29+
30+
valid.forEach(token => {
31+
test(`street_proper_names: ${token}`, (t) => {
32+
let s = classify(token)
33+
t.deepEqual(s.classifications, {
34+
StreetProperNameClassification: new StreetProperNameClassification(0.7)
35+
})
36+
t.end()
37+
})
38+
})
39+
}
40+
41+
module.exports.all = (tape, common) => {
42+
function test (name, testFunction) {
43+
return tape(`StreetProperNameClassifier: ${name}`, testFunction)
44+
}
45+
46+
for (var testCase in module.exports.tests) {
47+
module.exports.tests[testCase](test, common)
48+
}
49+
}

classifier/scheme/street.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,32 @@
11
const StreetClassification = require('../../classification/StreetClassification')
22

33
module.exports = [
4+
{
5+
// Broadway Market
6+
confidence: 0.80,
7+
Class: StreetClassification,
8+
scheme: [
9+
{
10+
is: ['StreetProperNameClassification'],
11+
not: ['StreetClassification', 'IntersectionClassification']
12+
},
13+
{
14+
is: ['StreetSuffixClassification'],
15+
not: ['StreetClassification', 'IntersectionClassification']
16+
}
17+
]
18+
},
19+
{
20+
// Broadway
21+
confidence: 0.82,
22+
Class: StreetClassification,
23+
scheme: [
24+
{
25+
is: ['StreetProperNameClassification'],
26+
not: ['StreetClassification', 'IntersectionClassification']
27+
}
28+
]
29+
},
430
{
531
// Main Street
632
confidence: 0.82,

parser/AddressParser.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const UnitTypeUnitClassifier = require('../classifier/UnitTypeUnitClassifier')
88
const PostcodeClassifier = require('../classifier/PostcodeClassifier')
99
const StreetPrefixClassifier = require('../classifier/StreetPrefixClassifier')
1010
const StreetSuffixClassifier = require('../classifier/StreetSuffixClassifier')
11+
const StreetProperNameClassifier = require('../classifier/StreetProperNameClassifier')
1112
const RoadTypeClassifier = require('../classifier/RoadTypeClassifier')
1213
const ToponymClassifier = require('../classifier/ToponymClassifier')
1314
const CompoundStreetClassifier = require('../classifier/CompoundStreetClassifier')
@@ -56,6 +57,7 @@ class AddressParser extends Parser {
5657
new PostcodeClassifier(),
5758
new StreetPrefixClassifier(),
5859
new StreetSuffixClassifier(),
60+
new StreetProperNameClassifier(),
5961
new RoadTypeClassifier(),
6062
new ToponymClassifier(),
6163
new CompoundStreetClassifier(),

resources/pelias/dictionaries/libpostal/en/street_types.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,7 @@ furlong
1010
# 1384 Cambridge beltway, Cambridge, MD 21613, USA
1111
beltway
1212

13+
# https://github.com/pelias/parser/issues/140
14+
!broadway|bdwy|bway|bwy|brdway
15+
!esplanade|esp|espl
16+
market
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
cité|cite
22
cités|cites
3+
4+
# https://github.com/pelias/parser/pull/141#issuecomment-895230721
5+
!esplanades|esps

resources/pelias/dictionaries/whosonfirst/locality/name:eng_x_preferred.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,7 @@ bronx
7575
!wisconsin
7676
!wyoming
7777

78+
# https://github.com/pelias/parser/issues/140
79+
!broadway
80+
!esplanade
81+
!market
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# https://github.com/pelias/parser/issues/140
2+
!broadway

test/address.deu.test.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,21 @@ const testcase = (test, common) => {
2727
{ locality: 'Munich' }, { country: 'Germany' }
2828
])
2929

30+
assert('Esplanade, Berlin', [
31+
{ street: 'Esplanade' },
32+
{ locality: 'Berlin' }
33+
])
34+
3035
assert('Esplanade 17, Berlin', [
3136
{ street: 'Esplanade' }, { housenumber: '17' },
3237
{ locality: 'Berlin' }
3338
])
3439

40+
assert('17 Esplanade, Berlin', [
41+
{ housenumber: '17' }, { street: 'Esplanade' },
42+
{ locality: 'Berlin' }
43+
])
44+
3545
assert('Königsallee Düsseldorf', [
3646
{ street: 'Königsallee' },
3747
{ locality: 'Düsseldorf' }

test/address.gbr.test.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,19 @@ const testcase = (test, common) => {
44
assert('Rushendon Furlong', [
55
{ street: 'Rushendon Furlong' }
66
])
7+
8+
// Valid street name in London
9+
assert('Broadway Market, London', [
10+
{ street: 'Broadway Market' },
11+
{ locality: 'London' }
12+
])
13+
14+
// 'The Dove', a pub on Broadway Market
15+
assert('24-28 Broadway Market, London', [
16+
{ housenumber: '24-28' },
17+
{ street: 'Broadway Market' },
18+
{ locality: 'London' }
19+
])
720
}
821

922
module.exports.all = (tape, common) => {

test/address.usa.test.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,36 @@ const testcase = (test, common) => {
249249
{ locality: 'boston' },
250250
{ region: 'ma' }
251251
])
252+
253+
// https://github.com/pelias/parser/issues/140
254+
assert('Broadway, Manhattan', [
255+
{ street: 'Broadway' },
256+
{ locality: 'Manhattan' }
257+
])
258+
assert('24 Broadway, Manhattan', [
259+
{ housenumber: '24' }, { street: 'Broadway' },
260+
{ locality: 'Manhattan' }
261+
])
262+
assert('Broadway 24, Manhattan', [
263+
{ street: 'Broadway' }, { housenumber: '24' },
264+
{ locality: 'Manhattan' }
265+
])
266+
assert('East Broadway, Manhattan', [
267+
{ street: 'East Broadway' },
268+
{ locality: 'Manhattan' }
269+
])
270+
assert('24 East Broadway, Manhattan', [
271+
{ housenumber: '24' }, { street: 'East Broadway' },
272+
{ locality: 'Manhattan' }
273+
])
274+
assert('West Broadway, Manhattan', [
275+
{ street: 'West Broadway' },
276+
{ locality: 'Manhattan' }
277+
])
278+
assert('24 West Broadway, Manhattan', [
279+
{ housenumber: '24' }, { street: 'West Broadway' },
280+
{ locality: 'Manhattan' }
281+
])
252282
}
253283

254284
module.exports.all = (tape, common) => {

0 commit comments

Comments
 (0)