今天早晨我在办公室遇到了一个问题。
我需要找一种方法,将列表中的字符串分组。很难解释,下面是一个例子:
假设我有以下列表:
['MONTREAL EDUCATION BOARD', 'Île de Montréal', 'Montréal',
'Ville de Montréal', 'MONTREAL CITY', 'Monrtéal', 'Mont-réal',
'Toronto', 'Toronto city', 'Tornoto', 'What is this', 'Bananasplit',
'Banana', 'StLouis', 'St-Louis', 'Saint Louis']
我需要找到一种方法根据它们的相似性将这些值分组在一起:
[['MONTREAL EDUCATION BOARD'],
['Île de Montréal', 'Montréal','Ville de Montréal', 'MONTREAL CITY', 'Monrtéal', 'Mont-réal'],
['Toronto', 'Toronto city', 'Tornoto'],
['anything'],
['Bananasplit', 'Banana'],
['StLouis', 'St-Louis', 'Saint Louis']
]
那将是最完美的情况。显然它可能会有错误(并且确实会有)。我需要对大约10,000个列表执行此操作,其中每个列表包含5到15,000个字符串。我需要尽量减少错误,并获得最好的分组。
我正在使用略微修改过的fuzzywuzzy
版本。我首先去掉重音符号并将所有字母大写,以获得更准确的Levenshtein距离。
我尝试设置一个阈值(比如80),遍历列表,将每个字符串分组并删除重复元素。显然,这不是我需要的结果,因为我需要每个元素仅出现在一个列表中(而这种情况并非总是成立,因为A可以与B联系,B可以与C联系,但A不能与C联系)。
groups = []
for curr in lst:
curr_grp = []
for item in lst:
ratio = normalized.partial_ratio(curr, item)
if ratio > SET_THRESHOLD:
curr_grp.append((item, ratio))
groups.append(curr_grp)
我认为可以从我的输出中找到最优配置的方法:
[[('MONTREAL EDUCATION BOARD', 100),
('Montréal', 100), # Will probably have to use ratio() and not partial_ratio() because
('Monrtéal', 88), # this can't happen, EDUCATION BOARD is NOT Montreal
('Mont-réal', 89)],
[('Île de Montréal', 100),
('Montréal', 100),
('Ville de Montréal', 93),
('Monrtéal', 88),
('Mont-réal', 94)],
[('MONTREAL EDUCATION BOARD', 100),
('Île de Montréal', 100),
('Montréal', 100),
('Ville de Montréal', 100),
('MONTREAL CITY', 100),
('Monrtéal', 88),
('Mont-réal', 88)],
[('Île de Montréal', 93),
('Montréal', 100),
('Ville de Montréal', 100),
('Monrtéal', 88),
('Mont-réal', 94)],
[('Montréal', 100),
('MONTREAL CITY', 100),
('Monrtéal', 88),
('Mont-réal', 89)],
[('MONTREAL EDUCATION BOARD', 88),
('Île de Montréal', 88),
('Montréal', 88),
('Ville de Montréal', 88),
('MONTREAL CITY', 88),
('Monrtéal', 100)],
[('MONTREAL EDUCATION BOARD', 89),
('Île de Montréal', 94),
('Montréal', 88),
('Ville de Montréal', 94),
('MONTREAL CITY', 89),
('Mont-réal', 100)],
[('Toronto', 100), ('Toronto city', 100), ('Tornoto', 86)],
[('Toronto', 100), ('Toronto city', 100), ('Tornoto', 86)],
[('Toronto', 86), ('Toronto city', 86), ('Tornoto', 100)],
[('What is this', 100)],
[('Bananasplit', 100), ('Banana', 100)],
[('Bananasplit', 100), ('Banana', 100)],
[('StLouis', 100), ('St-Louis', 86), ('Saint Louis', 86)],
[('StLouis', 86), ('St-Louis', 100)],
[('StLouis', 86), ('Saint Louis', 100)]]
是否可能找到这个列表中最优的子集,使得每个元素只在一个组中出现?(因此具有最高分数?)考虑到我的列表将更大,因此我无法测试每个配置,因为这将需要很多时间。
否则,有没有其他更有效的方法可以做到我想做的事情?
谢谢!