Skip to content

Commit

Permalink
[已完成]: getArea (#5)
Browse files Browse the repository at this point in the history
* feat(utility): add get-area utility function

* fix(@xstools/utility): small fix

* fix(utility): improve getArea utility function and addressNormalizer

* feat(utility): improve getArea utility function and addressNormalizer

* refactor(utility): optimize address cleaning functions

* refactor: rename

* test: update getDistrict test

* docs: update changeset

---------

Co-authored-by: bingtsingw <10382462+bingtsingw@users.noreply.github.com>
  • Loading branch information
KenjiGinjo and bingtsingw authored Jul 13, 2024
1 parent 202856d commit bb9cbb5
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/eight-moose-push.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@xstools/utility': minor
---

增加 getDistrict: 根据title address 获取城市区名
76 changes: 76 additions & 0 deletions packages/utility/src/misc/get-district.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { describe, expect, test } from 'bun:test';
import { addressTrimEnd, addressTrimParenthesis, districtStartWith, getDistrict } from './get-district';

describe('misc', () => {
test('getDistrict', () => {
// 标准地址
[
{
address: '北京市北京市大兴区行远街道101号',
title: '星巴克',
expected: '大兴区',
},

{
address: '广东省深圳市罗湖区科技园路0号',
title: '',
expected: '罗湖区',
},
{
address: '北京市北京市大兴区行远街道101号',
title: '大兴星巴克',
expected: '',
},
].forEach(({ address, title, expected }) => expect(getDistrict({ address, title })).toEqual(expected));

// 特殊地址
[
{
address: '',
title: '',
expected: '',
},
{
address: '',
title: '大兴星巴克',
expected: '',
},
{
address: '上海市上海市黄浦区南京西路325号上海市历史博物馆内',
title: 'COFFEE满坡栗咖啡(上海历史博物馆臻选店)',
expected: '黄浦区',
},
{
address: '上海市静安区乌鲁木齐北路4号(近市西中学后门)',
title: 'SilverFlow银流咖啡(元善里店)',
expected: '静安区',
},
{
address: '吉林省长春市朝阳区吉大南校北门致远街408号',
title: 'Im Fine Cafe Bar 吉林省长春市朝阳区吉大南校',
expected: '朝阳区',
},
].forEach(({ address, title, expected }) => expect(getDistrict({ address, title })).toEqual(expected));
});

test('addressTrimParenthesis', () => {
expect(addressTrimParenthesis('hello')).toEqual('hello');
expect(addressTrimParenthesis('北京市海淀区知春路[五道口]10号')).toEqual('北京市海淀区知春路10号');
expect(addressTrimParenthesis('上海市黄浦区南京东路100号(步行街)')).toEqual('上海市黄浦区南京东路100号');
expect(addressTrimParenthesis('深圳市南山区高新南一道(软件园)[南门]300号')).toEqual('深圳市南山区高新南一道300号');
});

test('addressTrimEnd', () => {
expect(addressTrimEnd('hello')).toEqual('hello');
expect(addressTrimEnd('北京市海淀区知春路10号xxxx')).toEqual('北京市海淀区知春路10号');
});

test('districtStartWith', () => {
expect(districtStartWith({ title: '朝阳区xx酒吧', district: '朝阳区' })).toBeFalse();
expect(districtStartWith({ title: 'xx朝阳区xx酒吧', district: '朝阳区' })).toBeFalse();
expect(districtStartWith({ title: 'xxx朝阳区xx酒吧', district: '朝阳区' })).toBeFalse();

expect(districtStartWith({ title: 'xxxx朝阳区xx酒吧', district: '朝阳区' })).toBeTrue();
expect(districtStartWith({ title: 'xx酒吧', district: '朝阳区' })).toBeTrue();
});
});
57 changes: 57 additions & 0 deletions packages/utility/src/misc/get-district.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
export const addressTrimParenthesis = (address: string) => {
const brackets = ['()', '[]', '{}', '<>', '()', '【】', '{}', '《》', '〈〉', '〔〕', '〖〗', '〘〙'];
const left: string[] = [];
const right: string[] = [];

brackets.forEach((bracket) => {
const [open, close] = bracket.split('').filter((bracket) => bracket.trim());
left.push(open!);
right.push(close!);
});

const regexParts = left.flatMap((open) => right.map((close) => `\\${open}[^\\${open}\\${close}]*\\${close}`));

const regexPattern = regexParts.join('|');
return address.replace(new RegExp(regexPattern, 'g'), '');
};

export const addressTrimEnd = (address: string) => {
return address.replace(/((?:街|道|路)\d+号).*/, '$1');
};

/**
* 判断是否为有效的区域
* - 如果 title 中从第 0 到第 3 个字符开始的子串与 district 或去掉“区”后的 district 相匹配,则认为无效。
* - 后续可以添加更多的规则
*/
export const districtStartWith = ({ title, district }: { title: string; district: string }): boolean => {
const trimmedDistrict = district.replace('区', '');
for (let i = 0; i <= 3; i++) {
if (title.slice(i).startsWith(district) || title.slice(i).startsWith(trimmedDistrict)) {
return false;
}
}

return true;
};

export const getDistrict = ({ title = '', address }: { title?: string; address?: string }): string => {
if (!address) {
return '';
}

const cleanedAddress = addressTrimEnd(addressTrimParenthesis(address));

const regex =
/(?<_>[^省]+省|.+自治区|[^澳门]+澳门|[^香港]+香港|[^市]+市)?(?<__>[^自治州]+自治州|[^特别行政区]+特别行政区|[^市]+市|.*?地区|.*?行政单位|.+盟|市辖区|[^县]+县)(?<district>[^县]+县|[^市]+市|[^镇]+镇|[^区]+区|[^乡]+乡|.+场|.+旗|.+海域|.+岛)?(?<___>.*)/;
const match = cleanedAddress.match(regex);

const district = match?.groups?.['district'];
if (district) {
if (districtStartWith({ title, district })) {
return district;
}
}

return '';
};
1 change: 1 addition & 0 deletions packages/utility/src/misc/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './get-distance';
export { getDistrict } from './get-district';
export * from './stringify';

0 comments on commit bb9cbb5

Please sign in to comment.