Сопоставление ближайшей строки с другой строкой (футбольные команды)?

#python-3.x #string #levenshtein-distance

#python-3.x #строка #левенштейн-расстояние

Вопрос:

Я работаю над стандартизацией некоторых данных, которые я получаю через футбольный API.

У меня есть функция с тремя входными данными, home , away (две футбольные команды) и списком строк, которые содержат команду home или away , но они могут называться иначе, чем входные home и away .

Моя цель — заменить все экземпляры home в списке на 1, а все экземпляры away в списке на 2.

Вот несколько примеров входных данных:

 home: "Manchester United", away: "Liverpool", list = ["Man Utd and Yes", "Liverpool and No", "Man Utd and No", "Liverpool and Yes"]

home: "Manchester United", away: "Manchester City", list = ["Man Utd and Yes", "Man City and No", "Man Utd and No", "Man City and Yes"]

home: "Paris Saint Germain", away: "Monaco", list = ["Monaco and Yes", "Monaco and No", "PSG and Yes", "PSG and No"]

home: "Brighton amp; Hove Albion", away: "Chelsea", list = ["Chelsea and No", "Brighton and Yes", "Chelsea and Yes", "Brighton and No"]
  

Обратите внимание, названия команд в списке совпадают (вы никогда не увидите «Манчестер Юнайтед» и «Да», «Манчестер Юнайтед» и «Нет» в одном списке).

Теперь, как мне сопоставить команды? Это то, что я делал до сих пор:

 def standardise(home, away, lst):
   for i, v in enumerate(lst):
      team = v.split("and")[0]
   
      if team in home or home in team:
         lst[i] = v.replace(team, "1")
         for j, k in enumerate(lst):
            new_team = k.split("and")[0]
            if new_team != i and team != new_team:
               lst[j] = k.replace(new_team, "2")
            else:
               lst[j] = k.replace(new_team, "1")
         
      elif team in away or away in team:
         # same code as above but for away 

      elif enchant.utils.levenshtein(team, home) >= 
           enchant.utils.levenshtein(team, away):
      
         lst[i] = v.replace(team, "2")

      else:
         lst[i] = v.replace(team, "1")
  

Где расстояние Левенштейна измеряет минимальное количество правок, которые вам нужно сделать, чтобы заменить последовательность из одного слова на другую.

Теперь этот метод не работает в 100% случаев, например, с акронимами, метод, похоже, дает сбой.

Есть ли лучший способ сделать это, возможно, более конкретный метод, который кто-нибудь может придумать?

Ответ №1:

Fuzzywuzzy идеально подходит для этого. довольно просто документы тоже

 from fuzzywuzzy import process

def standardise(home, away, lst):
    home_away = {home:'1', away:'2'}
    choices = [home, away]
    
    print ([ home_away[process.extractOne(each, choices)[0]] for each in lst ])


home = "Manchester United"
away = "Liverpool", 
lst = ["Man Utd and Yes", "Liverpool and No", "Man Utd and No", "Liverpool and Yes"]
standardise(home, away, lst)


home = "Manchester United" 
away = "Manchester City" 
lst = ["Man Utd and Yes", "Man City and No", "Man Utd and No", "Man City and Yes"]
standardise(home, away, lst)


home = "Paris Saint Germain" 
away = "Monaco" 
lst = ["Monaco and Yes", "Monaco and No", "PSG and Yes", "PSG and No"]
standardise(home, away, lst)


home = "Brighton amp; Hove Albion" 
away = "Chelsea" 
lst = ["Chelsea and No", "Brighton and Yes", "Chelsea and Yes", "Brighton and No"]
standardise(home, away, lst)
  

Вывод:

 ['1', '2', '1', '2']
['1', '2', '1', '2']
['2', '2', '1', '1']
['2', '1', '2', '1']
  

Ответ №2:

Вы можете попробовать сначала убрать гласные, чтобы каждое название было ближе к его аббревиатуре, а затем применить Levenshtein.

И также проверьте fuzzywuzzy.