Я написал пакет Python, целью которого является решение этой проблемы:
pip install fuzzymatcher
Здесь вы можете найти repo здесь и docs здесь .
Базовое использование:
Для двух фреймов данных df_left
и df_right
, которые вы хотите использовать нечеткое соединение, вы можете написать следующее:
from fuzzymatcher import link_table, left join
# Columns to match on from df_left
left_on = ["fname", "mname", "lname", "dob"]
# Columns to match on from df_right
right_on = ["name", "middlename", "surname", "date"]
# The link table potentially contains several matches for each record
fuzzymatcher.link_table(df_left, df_right, left_on, right_on)
Или если вы просто хотите установить ссылку в ближайшем совпадении:
fuzzymatcher.fuzzy_left_join(df_left, df_right, left_on, right_on)
>>> ["foo", "bar", "baz"].index("bar")
1
Ссылка: Структуры данных> Больше в Списках
Примечание, которое, в то время как это - возможно, самый чистый способ ответить на вопрос , как спросили , index
, довольно слабый компонент list
API, и я не могу помнить прошлый раз, когда я использовал его в гневе. На это указали мне в комментариях, что, потому что на этот ответ в большой степени ссылаются, это должно быть сделано больше завершенным. Некоторые протесты [приблизительно 117] следуют. Это, вероятно, стоит первоначально смотреть на docstring для него:
>>> print(list.index.__doc__)
L.index(value, [start, [stop]]) -> integer -- return first index of value.
Raises ValueError if the value is not present.
index
вызов проверяет каждый элемент списка в порядке, пока это не находит соответствие. Если Ваш список длинен, и Вы не знаете примерно, где в списке он происходит, этот поиск мог стать узким местом. В этом случае необходимо рассмотреть различную структуру данных. Обратите внимание, что, если Вы знаете примерно, где найти соответствие, можно дать index
подсказка. Например, в этом отрывке, l.index(999_999, 999_990, 1_000_000)
примерно пять порядков величины быстрее, чем прямой l.index(999_999)
, потому что первый только должен искать 10 записей, в то время как последние поиски миллион:
>>> import timeit
>>> timeit.timeit('l.index(999_999)', setup='l = list(range(0, 1_000_000))', number=1000)
9.356267921015387
>>> timeit.timeit('l.index(999_999, 999_990, 1_000_000)', setup='l = list(range(0, 1_000_000))', number=1000)
0.0004404920036904514
А звонят в [1 112], перерывает список в порядке, пока это не находит соответствие, и остановки там. , Если Вы ожидаете нуждаться в индексах большего количества соответствий, необходимо использовать понимание списка или выражение генератора.
>>> [1, 1].index(1)
0
>>> [i for i, e in enumerate([1, 2, 1]) if e == 1]
[0, 2]
>>> g = (i for i, e in enumerate([1, 2, 1]) if e == 1)
>>> next(g)
0
>>> next(g)
2
Большинство мест, где я однажды использовал бы index
, я теперь, использует понимание списка или выражение генератора, потому что они более generalizable. Таким образом, если Вы рассматриваете достижение для [1 114], смотрите на эти превосходные функции Python.
, А звонят в [1 115] результаты в ValueError
если объект не существующий.
>>> [1, 1].index(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: 2 is not in list
, Если объект не мог бы присутствовать в списке, Вы должны любой
index
вызов в try/except
блок, который ловит ValueError
(вероятно, быстрее, по крайней мере, то, когда список для поиска длинен, и объект, обычно присутствует.) Одна вещь, которая действительно полезна в изучении Python, состоит в том, чтобы использовать интерактивную функцию справки:
>>> help(["foo", "bar", "baz"])
Help on list object:
class list(object)
...
|
| index(...)
| L.index(value, [start, [stop]]) -> integer -- return first index of value
|
, который будет часто приводить Вас к методу, который Вы ищете.
для предотвращения ValueError можно сделать функцию, чтобы сделать это, хотя класс также работал бы.
def findInList(List, item):
try:
return List.index(item)
except ValueError:
return -1
единственная проблема состоит в том, что это могло заставить твердое разыскивать ошибку; то же относилось бы к другим числам.
Однако, если это возвращает что-нибудь кроме числа, это будет, вероятно, использоваться в качестве индекса списка и неизбежно бросит ошибку так или иначе.
, По-моему, предполагая, что что-то пошло не так, как надо, если объект не найден, лучше использовать try
- except
, но с пользовательским сообщением об ошибке, и таким образом это не сделает отладку тяжелее, и при этом возвращаемое значение не будет иметь значения:
# python 3.x
class itemNotFoundInListError(Exception):
pass
def findInList(List, item):
try:
return List.index(item)
except ValueError:
raise itemNotFoundInListError(f"List `{List}` does not contain `{item}.`")