У меня есть автономный процесс загрузки данных CSV, который я закодировал на Java, который должен использовать нечеткое соответствие строк. Это определенно не идеально, но у меня нет выбора. Я сопоставляю имя и фамилию, и я кеширую все возможности в начале прогона. После нахождения совпадения, мне тогда нужно, чтобы этот объект человека несколько мест во время прогона. Я использовал guava Objects.hashCode()
для создания хэша из первого имени и имени.
Механизм кэширования выглядит следующим образом:
Map<Integer,PersonDO> personCache = Maps.newHashMap();
for(PersonDO p: dao.getPeople()) {
personCache.put(Objects.hashCode(p.getFirstName(),p.getLastName()), p);
}
В большинстве случаев я получаю хиты по имени/фамилии, но когда он промахивается, я возвращаюсь с помощью Apache StringUtils.getLevenshteinDistance()
, чтобы попробовать и сопоставить его. Вот как идет логика соответствия:
person = personCache.get(Objects.hashCode(firstNameFromCSV,lastNameFromCSV));
if(person == null) {//fallback to fuzzy matching
person = findClosetMatch(firstNameFromCSV+lastNameFromCSV);
}
Это метод findClosetMatch()
:
private PersonDO findClosetMatch(String name) {
int min = 15;//initial value
int testVal=0;
PersonDO matchedPerson = null;
for(PersonDO person: personCache.values()) {
testVal = StringUtils.getLevenshteinDistance(name,person.getFirstName()+person.getLastName());
if( testVal < min ) {
min = testVal;
matchedPerson = person;
}
}
if(matchedPerson == null) {
throw new Exception("Unable to find person: " + name)
}
return matchedPerson;
}
Это отлично работает с простыми орфографическими ошибками, опечатками и сокращенными именами (например, Mike- > Michael), но когда я полностью пропускаю одно из входящих имен в кеш, я возвращаю ложное положительное совпадение. Чтобы это не происходило, я установил минимальное значение в findClosetMatch()
равным 15 (т.е. не более 15 символов); он работает большую часть времени, но у меня все еще было несколько неправильных совпадений: Mike Thompson
попадает на Mike Thomas
и т.д.
Вне зависимости от способа получения первичного ключа в загружаемом файле кто-нибудь видит способ улучшить этот процесс? Любые другие алгоритмы соответствия, которые могут помочь здесь?