使用Python中的正则表达式匹配大量字符串列表

10
我有一大串包含空格的字符串列表,比如“纽约”,“美利坚合众国”、“北卡罗来纳州”、“阿拉伯联合酋长国”、“大不列颠及北爱尔兰联合王国”等等,总共有5000多个这样的字符串。我有一大段文本,其中可能包含任何这些字符串(例如:“我去了纽约,在去北卡罗来纳的路上,并最终将前往阿拉伯联合酋长国。”)。最好的方法是如何有效地使用正则表达式来检测这些字符串在我的文本中是否存在?或者,我应该换一种思路,从文本中提取二元组,看看这个列表中的哪些字符串与这些二元组匹配?编辑:在与VoronoiPotato进行了有趣的讨论后,我开始认为更好的方法是对大字符串列表中的所有令牌建立索引,并使用以下函数实现:
def indexing_list(li):
    index_dict={}
    for i in rl(li):
        words=li[i].split()
        for j in rl(words):
            index=complex(i,j)
            word=words[j].lower()
            try:
                index_dict[word].append(index)
            except:
                index_dict[word]=[index]
    return index_dict

尝试使用此列表:

[u'United Kingdom of Great Britain and Northern Ireland', u'Democratic People\u2019s Republic of Korea', u'Democratic Republic of the Congo', u'Lao People\u2019s Democratic Republic', u'Saint Vincent and the Grenadines', u'United Republic of Tanzania', u'Iran (Islamic Republic of)', u'Central African Republic', u'Islamic Republic of Iran', u'United States of America', u'Bosnia and Herzegovina', u'Libyan Arab Jamahiriya', u'Saint Kitts and Nevis', u'Sao Tome and Principe', u'Syrian Arab Republic', u'United Arab Emirates', u'Antigua and Barbuda', u'Trinidad and Tobago', u'Dominican Republic', u'Russian Federation', u'Brunei Darussalam', u'Equatorial Guinea', u'Republic of Korea', u'Marshall Islands', u'Papua New Guinea', u'Solomon Islands', u'ComodRivadavia', u'Port-au-Prince', u'DumontDUrville', u'Czech Republic', u'United Kingdom', u'Dar es Salaam', u'Cambridge Bay', u'Coral Harbour', u'Port of Spain', u'Santo Domingo', u'St Barthelemy', u'Swift Current', u'Ujung Pandang', u'Yekaterinburg', u'South Georgia', u'C\xf4te d\u2019Ivoire', u"Cote d'Ivoire", u'Guinea-Bissau', u'Liechtenstein', u'United States', u'Johannesburg', u'Buenos Aires', u'Rio Gallegos', u'Blanc-Sablon', u'Campo Grande', u'Danmarkshavn', u'Dawson Creek', u'Indianapolis', u'North Dakota', u'Rankin Inlet', u'Scoresbysund', u'Longyearbyen', u'Kuala Lumpur', u'Antananarivo', u'Port Moresby', u'Burkina Faso', u'Saudi Arabia', u'Sierra Leone', u'South Africa', u'Turkmenistan', u'Addis Ababa', u'Brazzaville', u'Ouagadougou', u'El Salvador', u'Los Angeles', u'Mexico City', u'Pangnirtung', u'Porto Velho', u'Puerto Rico', u'Rainy River', u'Tegucigalpa', u'Thunder Bay', u'Yellowknife', u'Ho Chi Minh', u'Krasnoyarsk', u'Novosibirsk', u'Ulaanbaatar', u'Vladivostok', u'Broken Hill', u'Isle of Man', u'Kaliningrad', u'Guadalcanal', u'Afghanistan', u'Cock Island', u'El Salvador', u'Netherlands', u'New Zealand', u'Philippines', u'Saint Lucia', u'Switzerland', u'Timor-Leste', u'Casablanca', u'Libreville', u'Lubumbashi', u'Nouakchott', u'Porto-Novo', u'Costa Rica', u'Fort Wayne', u'Grand Turk', u'Guadeloupe', u'Hermosillo', u'Petersburg', u'Louisville', u'Monticello', u'Martinique', u'Montevideo', u'Montserrat', u'Paramaribo', u'Porto Acre', u'Rio Branco', u'St Vincent', u'Whitehorse', u'Antarctica', u'South Pole', u'Choibalsan', u'Phnom Penh', u'Ulan Bator', u'Cape Verde', u'Queensland', u'Yancowinna', u'Bratislava', u'Copenhagen', u'Luxembourg', u'San Marino', u'Simferopol', u'Zaporozhye', u'Kiritimati', u'Yugoslavia', u'Azerbaijan', u'Bangladesh', u'Cape Verde', u'Costa Rica', u'Kazakhstan', u'Kyrgyzstan', u'Luxembourg', u'Madagascar', u'Mauritania', u'Micronesia', u'Montenegro', u'Mozambique', u'San Marino', u'Seychelles', u'Tajikistan', u'Uzbekistan', u'Bujumbura', u'Mogadishu', u'Anchorage', u'Araguaina', u'Catamarca', u'Boa Vista', u'Chihuahua', u'Fortaleza', u'Glace Bay', u'Goose Bay', u'Guatemala', u'Guayaquil', u'Tell City', u'Vincennes', u'Menominee', u'Monterrey', u'New Salem', u'Sao Paulo', u'St Thomas', u'Vancouver', u'Ashkhabad', u'Chongqing', u'Chungking', u'Hong Kong', u'Jerusalem', u'Kamchatka', u'Pontianak', u'Pyongyang', u'Qyzylorda', u'Samarkand', u'Singapore', u'Vientiane', u'Jan Mayen', u'Reykjavik', u'St Helena', u'Australia', u'Lord Howe', u'Melbourne', u'Greenwich', u'Amsterdam', u'Bucharest', u'Gibraltar', u'Ljubljana', u'Mariehamn', u'Podgorica', u'Stockholm', u'Volgograd', u'Christmas', u'Kerguelen', u'Mauritius', u'Enderbury', u'Galapagos', u'Kwajalein', u'Marquesas', u'Pago Pago', u'Rarotonga', u'Tongatapu', u'Argentina', u'Australia', u'Guatemala', u'Indonesia', u'Lithuania', u'Mauritius', u'Nicaragua', u'Singapore', u'Sri Lanka', u'Swaziland', u'Macedonia', u'Venezuela', u'Blantyre', u'Djibouti', u'El Aaiun', u'Freetown', u'Gaborone', u'Khartoum', u'Kinshasa', u'Monrovia', u'Ndjamena', u'Sao Tome', u'Timbuktu', u'Windhoek', u'Anguilla', u'La Rioja', u'San Juan', u'San Luis', u'Asuncion', u'Atikokan', u'Barbados', u'Dominica', u'Edmonton', u'Eirunepe', u'Ensenada', u'Kentucky', u'Mazatlan', u'Miquelon', u'Montreal', u'New York', u'Resolute', u'Santiago', u'Shiprock', u'St Johns', u'St Kitts', u'St Lucia', u'Winnipeg', u'Ashgabat', u'Calcutta', u'Damascus', u'Dushanbe', u'Istanbul', u'Jayapura', u'Katmandu', u'Makassar', u'Sakhalin', u'Shanghai', u'Tashkent', u'Tel Aviv', u'Atlantic', u'Adelaide', u'Brisbane', u'Canberra', u'Lindeman', u'Tasmania', u'Victoria', u'Belgrade', u'Brussels', u'Budapest', u'Chisinau', u'Guernsey', u'Helsinki', u'Sarajevo', u'Tiraspol', u'Uzhgorod', u'Auckland', u'Funafuti', u'Honolulu', u'Johnston', u'Pitcairn', u'Barbados', u'Botswana', u'Bulgaria', u'Cambodia', u'Cameroon', u'Colombia', u'Djibouti', u'Dominica', u'Ethiopia', u'Holy See', u'Honduras', u'Kiribati', u'Malaysia', u'Maldives', u'Mongolia', u'Pakistan', u'Paraguay', u'Portugal', u'Slovakia', u'Slovenia', u'Suriname', u'Thailand', u'Tanzania', u'Viet Nam', u'Zimbabwe', u'Anguilla', u'Abidjan', u'Algiers', u'Conakry', u'Kampala', u'Mbabane', u'Nairobi', u'Tripoli', u'America', u'Antigua', u'Cordoba', u'Mendoza', u'Tucuman', u'Ushuaia', u'Caracas', u'Cayenne', u'Chicago', u'Curacao', u'Detroit', u'Godthab', u'Grenada', u'Halifax', u'Indiana', u'Marengo', u'Winamac', u'Iqaluit', u'Managua', u'Marigot', u'Moncton', u'Nipigon', u'Noronha', u'Phoenix', u'Rosario', u'Tijuana', u'Toronto', u'Tortola', u'Yakutat', u'McMurdo', u'Rothera', u'Baghdad', u'Bahrain', u'Bangkok', u'Bishkek', u'Colombo', u'Irkutsk', u'Jakarta', u'Karachi', u'Kashgar', u'Kolkata', u'Kuching', u'Magadan', u'Nicosia', u'Rangoon', u'Tbilisi', u'Thimphu', u'Yakutsk', u'Yerevan', u'Bermuda', u'Madeira', u'Stanley', u'Andorra', u'Belfast', u'Tallinn', u'Vatican', u'Vilnius', u'Mayotte', u'Reunion', u'Chatham', u'Fakaofo', u'Gambier', u'Norfolk', u'Albania', u'Algeria', u'Armenia', u'Austria', u'Bahamas', u'Bahrain', u'Belarus', u'Belgium', u'Bolivia', u'Burundi', u'Comoros', u'Croatia', u'Denmark', u'Ecuador', u'Eritrea', u'Estonia', u'Finland', u'Georgia', u'Germany', u'Grenada', u'Hungary', u'Iceland', u'Ireland', u'Jamaica', u'Lebanon', u'Lesotho', u'Liberia', u'Morocco', u'Myanmar', u'Namibia', u'Nigeria', u'Moldova', u'Romania', u'Senegal', u'Somalia', u'Tunisia', u'Ukraine', u'Uruguay', u'Vanuatu', u'Asmara', u'Asmera', u'Bamako', u'Bangui', u'Banjul', u'Bissau', u'Douala', u'Harare', u'Kigali', u'Luanda', u'Lusaka', u'Malabo', u'Maputo', u'Maseru', u'Niamey', u'Belize', u'Bogota', u'Cancun', u'Cayman', u'Cuiaba', u'Dawson', u'Denver', u'Havana', u'Inuvik', u'Juneau', u'La Paz', u'Maceio', u'Manaus', u'Merida', u'Nassau', u'Recife', u'Regina', u'Virgin', u'Mawson', u'Palmer', u'Vostok', u'Arctic', u'Almaty', u'Anadyr', u'Aqtobe', u'Beirut', u'Brunei', u'Harbin', u'Kuwait', u'Manila', u'Muscat', u'Riyadh', u'Saigon', u'Taipei', u'Tehran', u'Thimbu', u'Urumqi', u'Azores', u'Canary', u'Faeroe', u'Currie', u'Darwin', u'Hobart', u'Sydney', u'Europe', u'Athens', u'Berlin', u'Dublin', u'Jersey', u'Lisbon', u'London', u'Madrid', u'Geneva', u'Monaco', u'Moscow', u'Prague', u'Samara', u'Skopje', u'Tirane', u'Vienna', u'Warsaw', u'Zagreb', u'Zurich', u'Chagos', u'Comoro', u'Easter', u'Kosrae', u'Majuro', u'Midway', u'Noumea', u'Ponape', u'Saipan', u'Tahiti', u'Tarawa', u'Wallis', u'Andora', u'Angola', u'Belize', u'Bhutan', u'Brazil', u'Canada', u'Cyprus', u'France', u'Gambia', u'Greece', u'Guinea', u'Guyana', u'Israel', u'Jordan', u'Kuwait', u'Latvia', u'Malawi', u'Mexico', u'Monaco', u'Norway', u'Panama', u'Poland', u'Rwanda', u'Serbia', u'Sweden', u'Turkey', u'Tuvalu', u'Uganda', u'Zambia', u'Accra', u'Cairo', u'Ceuta', u'Dakar', u'Lagos', u'Tunis', u'Jujuy', u'Aruba', u'Bahia', u'Belem', u'Boise', u'Vevay', u'Thule', u'Casey', u'Davis', u'Syowa', u'Amman', u'Aqtau', u'Dacca', u'Dhaka', u'Dubai', u'Kabul', u'Macao', u'Macau', u'Qatar', u'Seoul', u'Tokyo', u'Faroe', u'Eucla', u'Perth', u'Malta', u'Minsk', u'Paris', u'Sofia', u'Vaduz', u'Cocos', u'Efate', u'Nauru', u'Palau', u'Samoa', u'Benin', u'Chile', u'China', u'Congo', u'Egypt', u'Gabon', u'Ghana', u'Haiti', u'India', u'Italy', u'Japan', u'Kenya', u'Libya', u'Malta', u'Nauru', u'Nepal', u'Niger', u'Palau', u'Qatar', u'Samoa', u'Spain', u'Sudan', u'Syria', u'Tonga', u'Yemen', u'Lome', u'Adak', u'Atka', u'Nuuk', u'Knox', u'Lima', u'Nome', u'Asia', u'Aden', u'Baku', u'Dili', u'Gaza', u'Hovd', u'Omsk', u'Oral', u'Zulu', u'Kiev', u'Oslo', u'Bonn', u'Riga', u'Rome', u'Mahe', u'Apia', u'Fiji', u'Guam', u'Niue', u'Truk', u'Wake', u'Chad', u'Cuba', u'Fiji', u'Iran', u'Iraq', u'Mali', u'Oman', u'Peru', u'Togo', u'GMT', u'Yap']

然后我开始分析我拥有的文本:

text='I went to New York and New Orleans and London and United States, Canada, and Egypt, Saudi Arabia'
text_words=text.split()

并尝试单独调查每个单词:

for i in rl(text_words):
    tw=text_words[i].lower()
    print i
    print tw
    print index_dict.get(tw)

这个方法看起来很快,但我不确定如何进一步进行


1
需要使用正则表达式吗?为什么不只是不区分大小写地检查这些字符串呢? - Waleed Khan
1
与所有正则表达式问题一样,您需要梳理出您想要匹配的模式。您是想像您的问题所暗示的那样仅匹配州/国家名称吗? - kevlar1818
1
@hmghaly 你认为正则表达式在内部是如何工作的呢? ;) - Izkata
1
@hmghaly 它们是在某些情况下非常有用的数据结构。一个图形是一种模糊的数据结构,其中元素相互连接(单向或双向)。trie是一种图形的实现,可用于将您的列表拆分为更可搜索的版本(也许;我对这种事情不太擅长)。 - Waleed Khan
1
嗯,我认为你没有理解我所说的索引的含义,这可以做得更快。你不需要在国家名称旁边加上I或J,只要正确组合对象的结构就可以维护对象。通过以唯一键(及其关联值)的方式组合对象,可以使我们几乎立即比较字符串。[[{hash('United'):'United'},{hash('States'):'States'}],[{hash('Bolivia'):'Bolivia'}]]通过这种方式组合对象,可以使我们几乎立即比较字符串。 - VoronoiPotato
显示剩余17条评论
6个回答

10
whitespaces_list=['New York','United States', 'United Arab Emirates']
large_text="I went to New York on my way to North Carolina, and eventually will be going to United Arab Emirates."
for i in whitespaces_list:
    if i in large_text:
        print i," Exist in Large text"

你是否正在寻找类似这样的东西?


这有点太简单了,对于非常大的列表可能不够高效... - hmghaly
正则表达式并不是神奇的。它们也会遍历列表。 - Yunchi
当然,他们不必检查每个字母,只需足够满足正则表达式的要求即可。话虽如此,这种情况下的正则表达式可能需要检查每个字母。 - VoronoiPotato
@VoronoiPotato 或许不需要检查每个字符,我们只需在每个单词边界检查第一个字符,如果接下来的字符串在列表中,则知道字符串的结束位置,并从此处开始... 我知道正则表达式中有这种前瞻,但我实际上不确定如何使用它... - hmghaly

7

正如大多数人所说,这取决于你的文本城市列表,使用timeit比较方法是选择哪种方式的最佳方法:

list = ['New York','United States', 'United Arab Emirates']
text = "I went to New York on my way to North Carolina, and eventually will be going to United Arab Emirates."

每个循环重复5次,总共循环1,000,000次的时间

timeit -n 1000000 -r 5 re.findall(token_regex, text)
1000000 loops, best of 5: 6.22 us per loop

timeit -n 1000000 -r 5 filter(lambda x: x in text, token_list)
1000000 loops, best of 5: 2.76 us per loop

def somefunc():
    for i in token_list:
        if i in text:
            pass

timeit -n 1000000 -r 5 somefunc()
1000000 loops, best of 5: 1.68 us per loop


t = [hash(x) for x in text.replace('.', '').replace(',','').split()] 
tl = [hash(x) for x in token_list]# this list contains single words, like "New" and "York" but not "New York"

def SomeFunc2():
    for x in tl:
        if x in t:
            pass

timeit -n 1000000 -r 5 SomeFunc2()
1000000 loops, best of 5: 6.26 us per loop

t = set([hash(x) for x in text.replace('.', '').replace(',','').split()])
tl = set(hash(x) for x in token_list])

timeit -n 1000000 -r 5 t.intersection(tl)
1000000 loops, best of 5: 1.75 us per loop

通过使用你的示例数据,for循环的使用看起来相当快...但是正如我所说,你必须使用更多实时数据进行测试。 < p > < em >< strong >编辑:好的,我猜使用更多实时数据会更好,所以我正在使用以下数据集重新计算结果:

list = [u'United Kingdom of Great Britain and Northern Ireland', u'Democratic People\u2019s Republic of Korea', u'Democratic Republic of the Congo', u'Lao People\u2019s Democratic Republic', u'Saint Vincent and the Grenadines', u'United Republic of Tanzania', u'Iran (Islamic Republic of)', u'Central African Republic', u'Islamic Republic of Iran', u'United States of America', u'Bosnia and Herzegovina', u'Libyan Arab Jamahiriya', u'Saint Kitts and Nevis', u'Sao Tome and Principe', u'Syrian Arab Republic', u'United Arab Emirates', u'Antigua and Barbuda', u'Trinidad and Tobago', u'Dominican Republic', u'Russian Federation', u'Brunei Darussalam', u'Equatorial Guinea', u'Republic of Korea', u'Marshall Islands', u'Papua New Guinea', u'Solomon Islands', u'ComodRivadavia', u'Port-au-Prince', u'DumontDUrville', u'Czech Republic', u'United Kingdom', u'Dar es Salaam', u'Cambridge Bay', u'Coral Harbour', u'Port of Spain', u'Santo Domingo', u'St Barthelemy', u'Swift Current', u'Ujung Pandang', u'Yekaterinburg', u'South Georgia', u'C\xf4te d\u2019Ivoire', u"Cote d'Ivoire", u'Guinea-Bissau', u'Liechtenstein', u'United States', u'Johannesburg', u'Buenos Aires', u'Rio Gallegos', u'Blanc-Sablon', u'Campo Grande', u'Danmarkshavn', u'Dawson Creek', u'Indianapolis', u'North Dakota', u'Rankin Inlet', u'Scoresbysund', u'Longyearbyen', u'Kuala Lumpur', u'Antananarivo', u'Port Moresby', u'Burkina Faso', u'Saudi Arabia', u'Sierra Leone', u'South Africa', u'Turkmenistan', u'Addis Ababa', u'Brazzaville', u'Ouagadougou', u'El Salvador', u'Los Angeles', u'Mexico City', u'Pangnirtung', u'Porto Velho', u'Puerto Rico', u'Rainy River', u'Tegucigalpa', u'Thunder Bay', u'Yellowknife', u'Ho Chi Minh', u'Krasnoyarsk', u'Novosibirsk', u'Ulaanbaatar', u'Vladivostok', u'Broken Hill', u'Isle of Man', u'Kaliningrad', u'Guadalcanal', u'Afghanistan', u'Cock Island', u'El Salvador', u'Netherlands', u'New Zealand', u'Philippines', u'Saint Lucia', u'Switzerland', u'Timor-Leste', u'Casablanca', u'Libreville', u'Lubumbashi', u'Nouakchott', u'Porto-Novo', u'Costa Rica', u'Fort Wayne', u'Grand Turk', u'Guadeloupe', u'Hermosillo', u'Petersburg', u'Louisville', u'Monticello', u'Martinique', u'Montevideo', u'Montserrat', u'Paramaribo', u'Porto Acre', u'Rio Branco', u'St Vincent', u'Whitehorse', u'Antarctica', u'South Pole', u'Choibalsan', u'Phnom Penh', u'Ulan Bator', u'Cape Verde', u'Queensland', u'Yancowinna', u'Bratislava', u'Copenhagen', u'Luxembourg', u'San Marino', u'Simferopol', u'Zaporozhye', u'Kiritimati', u'Yugoslavia', u'Azerbaijan', u'Bangladesh', u'Cape Verde', u'Costa Rica', u'Kazakhstan', u'Kyrgyzstan', u'Luxembourg', u'Madagascar', u'Mauritania', u'Micronesia', u'Montenegro', u'Mozambique', u'San Marino', u'Seychelles', u'Tajikistan', u'Uzbekistan', u'Bujumbura', u'Mogadishu', u'Anchorage', u'Araguaina', u'Catamarca', u'Boa Vista', u'Chihuahua', u'Fortaleza', u'Glace Bay', u'Goose Bay', u'Guatemala', u'Guayaquil', u'Tell City', u'Vincennes', u'Menominee', u'Monterrey', u'New Salem', u'Sao Paulo', u'St Thomas', u'Vancouver', u'Ashkhabad', u'Chongqing', u'Chungking', u'Hong Kong', u'Jerusalem', u'Kamchatka', u'Pontianak', u'Pyongyang', u'Qyzylorda', u'Samarkand', u'Singapore', u'Vientiane', u'Jan Mayen', u'Reykjavik', u'St Helena', u'Australia', u'Lord Howe', u'Melbourne', u'Greenwich', u'Amsterdam', u'Bucharest', u'Gibraltar', u'Ljubljana', u'Mariehamn', u'Podgorica', u'Stockholm', u'Volgograd', u'Christmas', u'Kerguelen', u'Mauritius', u'Enderbury', u'Galapagos', u'Kwajalein', u'Marquesas', u'Pago Pago', u'Rarotonga', u'Tongatapu', u'Argentina', u'Australia', u'Guatemala', u'Indonesia', u'Lithuania', u'Mauritius', u'Nicaragua', u'Singapore', u'Sri Lanka', u'Swaziland', u'Macedonia', u'Venezuela', u'Blantyre', u'Djibouti', u'El Aaiun', u'Freetown', u'Gaborone', u'Khartoum', u'Kinshasa', u'Monrovia', u'Ndjamena', u'Sao Tome', u'Timbuktu', u'Windhoek', u'Anguilla', u'La Rioja', u'San Juan', u'San Luis', u'Asuncion', u'Atikokan', u'Barbados', u'Dominica', u'Edmonton', u'Eirunepe', u'Ensenada', u'Kentucky', u'Mazatlan', u'Miquelon', u'Montreal', u'New York', u'Resolute', u'Santiago', u'Shiprock', u'St Johns', u'St Kitts', u'St Lucia', u'Winnipeg', u'Ashgabat', u'Calcutta', u'Damascus', u'Dushanbe', u'Istanbul', u'Jayapura', u'Katmandu', u'Makassar', u'Sakhalin', u'Shanghai', u'Tashkent', u'Tel Aviv', u'Atlantic', u'Adelaide', u'Brisbane', u'Canberra', u'Lindeman', u'Tasmania', u'Victoria', u'Belgrade', u'Brussels', u'Budapest', u'Chisinau', u'Guernsey', u'Helsinki', u'Sarajevo', u'Tiraspol', u'Uzhgorod', u'Auckland', u'Funafuti', u'Honolulu', u'Johnston', u'Pitcairn', u'Barbados', u'Botswana', u'Bulgaria', u'Cambodia', u'Cameroon', u'Colombia', u'Djibouti', u'Dominica', u'Ethiopia', u'Holy See', u'Honduras', u'Kiribati', u'Malaysia', u'Maldives', u'Mongolia', u'Pakistan', u'Paraguay', u'Portugal', u'Slovakia', u'Slovenia', u'Suriname', u'Thailand', u'Tanzania', u'Viet Nam', u'Zimbabwe', u'Anguilla', u'Abidjan', u'Algiers', u'Conakry', u'Kampala', u'Mbabane', u'Nairobi', u'Tripoli', u'America', u'Antigua', u'Cordoba', u'Mendoza', u'Tucuman', u'Ushuaia', u'Caracas', u'Cayenne', u'Chicago', u'Curacao', u'Detroit', u'Godthab', u'Grenada', u'Halifax', u'Indiana', u'Marengo', u'Winamac', u'Iqaluit', u'Managua', u'Marigot', u'Moncton', u'Nipigon', u'Noronha', u'Phoenix', u'Rosario', u'Tijuana', u'Toronto', u'Tortola', u'Yakutat', u'McMurdo', u'Rothera', u'Baghdad', u'Bahrain', u'Bangkok', u'Bishkek', u'Colombo', u'Irkutsk', u'Jakarta', u'Karachi', u'Kashgar', u'Kolkata', u'Kuching', u'Magadan', u'Nicosia', u'Rangoon', u'Tbilisi', u'Thimphu', u'Yakutsk', u'Yerevan', u'Bermuda', u'Madeira', u'Stanley', u'Andorra', u'Belfast', u'Tallinn', u'Vatican', u'Vilnius', u'Mayotte', u'Reunion', u'Chatham', u'Fakaofo', u'Gambier', u'Norfolk', u'Albania', u'Algeria', u'Armenia', u'Austria', u'Bahamas', u'Bahrain', u'Belarus', u'Belgium', u'Bolivia', u'Burundi', u'Comoros', u'Croatia', u'Denmark', u'Ecuador', u'Eritrea', u'Estonia', u'Finland', u'Georgia', u'Germany', u'Grenada', u'Hungary', u'Iceland', u'Ireland', u'Jamaica', u'Lebanon', u'Lesotho', u'Liberia', u'Morocco', u'Myanmar', u'Namibia', u'Nigeria', u'Moldova', u'Romania', u'Senegal', u'Somalia', u'Tunisia', u'Ukraine', u'Uruguay', u'Vanuatu', u'Asmara', u'Asmera', u'Bamako', u'Bangui', u'Banjul', u'Bissau', u'Douala', u'Harare', u'Kigali', u'Luanda', u'Lusaka', u'Malabo', u'Maputo', u'Maseru', u'Niamey', u'Belize', u'Bogota', u'Cancun', u'Cayman', u'Cuiaba', u'Dawson', u'Denver', u'Havana', u'Inuvik', u'Juneau', u'La Paz', u'Maceio', u'Manaus', u'Merida', u'Nassau', u'Recife', u'Regina', u'Virgin', u'Mawson', u'Palmer', u'Vostok', u'Arctic', u'Almaty', u'Anadyr', u'Aqtobe', u'Beirut', u'Brunei', u'Harbin', u'Kuwait', u'Manila', u'Muscat', u'Riyadh', u'Saigon', u'Taipei', u'Tehran', u'Thimbu', u'Urumqi', u'Azores', u'Canary', u'Faeroe', u'Currie', u'Darwin', u'Hobart', u'Sydney', u'Europe', u'Athens', u'Berlin', u'Dublin', u'Jersey', u'Lisbon', u'London', u'Madrid', u'Geneva', u'Monaco', u'Moscow', u'Prague', u'Samara', u'Skopje', u'Tirane', u'Vienna', u'Warsaw', u'Zagreb', u'Zurich', u'Chagos', u'Comoro', u'Easter', u'Kosrae', u'Majuro', u'Midway', u'Noumea', u'Ponape', u'Saipan', u'Tahiti', u'Tarawa', u'Wallis', u'Andora', u'Angola', u'Belize', u'Bhutan', u'Brazil', u'Canada', u'Cyprus', u'France', u'Gambia', u'Greece', u'Guinea', u'Guyana', u'Israel', u'Jordan', u'Kuwait', u'Latvia', u'Malawi', u'Mexico', u'Monaco', u'Norway', u'Panama', u'Poland', u'Rwanda', u'Serbia', u'Sweden', u'Turkey', u'Tuvalu', u'Uganda', u'Zambia', u'Accra', u'Cairo', u'Ceuta', u'Dakar', u'Lagos', u'Tunis', u'Jujuy', u'Aruba', u'Bahia', u'Belem', u'Boise', u'Vevay', u'Thule', u'Casey', u'Davis', u'Syowa', u'Amman', u'Aqtau', u'Dacca', u'Dhaka', u'Dubai', u'Kabul', u'Macao', u'Macau', u'Qatar', u'Seoul', u'Tokyo', u'Faroe', u'Eucla', u'Perth', u'Malta', u'Minsk', u'Paris', u'Sofia', u'Vaduz', u'Cocos', u'Efate', u'Nauru', u'Palau', u'Samoa', u'Benin', u'Chile', u'China', u'Congo', u'Egypt', u'Gabon', u'Ghana', u'Haiti', u'India', u'Italy', u'Japan', u'Kenya', u'Libya', u'Malta', u'Nauru', u'Nepal', u'Niger', u'Palau', u'Qatar', u'Samoa', u'Spain', u'Sudan', u'Syria', u'Tonga', u'Yemen', u'Lome', u'Adak', u'Atka', u'Nuuk', u'Knox', u'Lima', u'Nome', u'Asia', u'Aden', u'Baku', u'Dili', u'Gaza', u'Hovd', u'Omsk', u'Oral', u'Zulu', u'Kiev', u'Oslo', u'Bonn', u'Riga', u'Rome', u'Mahe', u'Apia', u'Fiji', u'Guam', u'Niue', u'Truk', u'Wake', u'Chad', u'Cuba', u'Fiji', u'Iran', u'Iraq', u'Mali', u'Oman', u'Peru', u'Togo', u'GMT', u'Yap']

list从@hmghaly的示例中获取,包含645个国家和城市

text = "Lorem ipsum dolor Turkey sit amet, Brussels consectetur adipisicing elit, sed do Santo Domingo eiusmod tempor incididunt ut labore Tell City et dolore magna aliqua. Ut Goose Bay enim ad minim veniam, Bahrain quis nostrud exercitation New Salem ullamco laboris nisi Mongolia ut aliquip ex ea Yekaterinburg commodo consequat. Chihuahua Duis aute irure dolor in Nouakchott reprehenderit in voluptate velit Ireland esse cillum dolore eu fugiat nulla Lome pariatur. Excepteur sint occaecat San Marino cupidatat non proident, Comoro sunt in culpa qui officia Belem deserunt mollit anim id est laborum"

文本切片是具有随机放置的国家/城市名称的经典Lorem ipsum文本,最终文本是将相同的文本连接51次的结果,总共包含4590个单词和30344个字母。(在此处写太长了,因此重复相同的文本)

时间基于每个循环包含2次重复的1,000个(之前我测试了1,000,000个)循环:

正则表达式

regex = '('+'|'.join(list)+')'
%timeit -n 1000 -r 2 re.findall(regex, text)
1000 loops, best of 2: 3.36 ms per loop

Lambda

%timeit -n 1000 -r 2 filter(lambda x: x in text, list)
1000 loops, best of 2: 140 ms per loop

循环语句
def somefunc():
    for i in list:
        if i in text:
            pass

%timeit -n 1000 -r 2 somefunc()
1000 loops, best of 2: 138 ms per loop

基数树

from radix_tree import RadixTree
Tokens = list(set(list))

trie = RadixTree()
for token in Tokens:
    trie.insert(token, token)

def FindMatches(trie, text):
    while 0 < len(text):
        try:
            test = text[:text.index(" ")]
        except ValueError:
            test = text

        for token in trie.search_prefix(test, 100):
            if text.startswith(token):
                pass # no need to print to screen

        try:
            text = text[text.index(" ") + 1:]
        except ValueError:
            break # End of string

%timeit -n 1000 -r 2 FindMatches(trie, text)
1000 loops, best of 2: 236 ms per loop

设置和正则表达式

def SomeMoreFunc():
    rgx = '([A-Z][A-Za-z]*)' #@VoronoiPotato's approach
    filtered_text = set(re.findall(rgx, text)) #make a set of all words that starts with a capital letter 
    for x in list:
         #we split city name if it is constucted with 2 or more words, and parse it to a set, then check if all parts of the string are in the filtered text. If yes, then our city is within our text body
        if set(x.split()).issubset(filtered_text):
            pass 

%timeit -n 1000 -r 2 SomeMoreFunc()
1000 loops, best of 2: 2.81 ms per loop

我使用了 @VoronoiPotato 的方法,并使用了 set


令牌索引

def indexing_list(li):
    index_dict={}
    for i in range(len(li)):
        words=li[i].split()
        for j in range(len(words)):
            index=complex(i,j)
            word=words[j].lower()
            try:
                index_dict[word].append(index)
            except:
                index_dict[word]=[index]
    return index_dict

def someFunc():
    ind_dic = indexing_list(lst)
    text_words=text.split()
    for i in range(len(text_words)):
        tw=text_words[i].lower()
        index_dict.get(tw)


%timeit -n 1000 -r 2 someFunc()
1000 loops, best of 2: 7.41 ms per loop

使用新的数据集时,明显应该使用正则表达式而不是简单的文本搜索,使用集合可以提高性能(通过裁剪相似单词并允许使用issubset进行更轻松和更快速的比较)。在这些方法中,基数树搜索的结果最差。对于先前的数据集,正则表达式的使用比文本搜索更糟糕...

编辑:附加了Token索引结果。但是,此示例仅搜索单个单词,并且无法控制具有两个或多个单词的城市名称。

另外,Set和Regex以及Token索引方法存在危险的漏洞,考虑城市名称

El Salvador

and following text:

Salvador Dali lorem ipsum dolor. El Dranges porte quantera. 

这两种方法都会将El SalvadorSalvadorEl匹配,因为它们会分割单词并分别搜索。


1
尽管如此,随着列表大小增长到实际使用的大小,lambda可能会失效(我不经常使用lambda,无法了解它们的增长情况:x) - VoronoiPotato
1
“lambda”是一个比较的例子。我的意思是,使用timeit真实数据是做出决策的最佳方式 (: - FallenAngel
是的,绝对同意,不过他也在寻找不同的测试方法 :)。 - VoronoiPotato
@FallenAngel,我刚刚在我的答案中添加了代码,您介意在相同条件下计时吗? - Izkata
1
我更新了答案,使用了更实时的数据集和新的结果,同时为了效率比较保留了旧的数据集和结果,以便根据数据集大小进行比较。 - FallenAngel
显示剩余3条评论

4

使用一个正则表达式来检查文本中的大写单词。这将大大减少检查所需的时间。

[A-Z][a-z]*

一旦你得到一个匹配(一个大写单词),检查它是否与列表中的第一个单词匹配,如果是,则将下一个匹配与列表中的第二个单词对齐,直到你获得了一个完全匹配。


这看起来是一个有用的想法,我还在寻找更多类似的想法,谢谢 :) - hmghaly
1
更多的想法,寻找连续大写字母的单词。许多国家由多个单词组成,而很少有专有名词由多个单词组成,例如:乍得(Chad)或斯蒂芬(Stephen)。 - VoronoiPotato
ID是内存地址,所以它不像ID那样。ID是唯一的,但如果你获取国家="Georgia"和州的ID="Georgia",它不会给你完全相同的数字。因为它是变量的ID,而不是描述变量中数据的东西。 - VoronoiPotato
这是我所说的一个例子:http://ideone.com/6RRSk。正如你所看到的,当单词相同时,输出的数字也完全相同。这将有助于加快速度。你可能认为这是个庞大的数字,需要很长时间,但计算机在比较一堆数字和一堆字母时要快得多。 - VoronoiPotato
1
我喜欢这个讨论的方向。也许将每个列表项中的每个标记进行索引并分配一个唯一的索引,然后对我们想要搜索的文本进行标记化,并获取相应的索引,识别找到的连续索引,这可能是一个不错的主意。这可行吗? - hmghaly
显示剩余6条评论

2

您可能会发现基数树是最有效的。

基本思路是将要搜索的文本转换为一棵树,以便于查找其他字符串。但是,由于您要搜索的标记中包含空格,因此您需要进行一些调整,以确定标记的最佳定义。

例如,每个X个单词的分组是一个标记,其中X是您要搜索的给定项目中单词的最大数量。例如:在标记长度为3个单词的情况下,“Everything is green over here.”的树将包含“Everything is green”、“is green over”和“green over here”。

考虑到问题中的示例(在上述内容发布后发布),我在下面的代码中反转了我上面建议的内容。要搜索的标记被添加到Trie / Radix树中,然后逐步搜索文本字符串。如果您要搜索的标记较少且要搜索的文本较多,则上面的删除线可能更有效。

这里有一个基数树的Python实现,所以您不必自己编写它,这是使用该基数树的实现:

from radix_tree import RadixTree
Tokens = list(set([.....the list in the question.....])) # 'El Salvador' is listed twice, this is to make it unique easily.

trie = RadixTree()
for token in Tokens:
   trie.insert(token, token)

def FindMatches(trie, text):
   while 0 < len(text):
      try:
         test = text[:text.index(" ")]
      except ValueError:
         test = text

      for token in trie.search_prefix(test, 100):
         if text.startswith(token):
            print token

      try:
         text = text[text.index(" ") + 1:]
      except ValueError:
         break # End of string

FindMatches(trie, "I went to New York and New Orleans and London and United States, Canada, and Egypt, Saudi Arabia")

注意:新奥尔良不在令牌列表中,而且加拿大和埃及在search_prefix内的Trie中找不到,因为测试字符串中包含“,”符号。

谢谢,这看起来很有希望。 - hmghaly

0

-1

无论实际的解析方法如何,由于您的数据非常大,您需要将它们存储在文件中,您可能已经以某种方式在这样做。以下是我认为最有效的将数据导入Python的方法:

search.txt - 您要搜索的字符串,“searchterms”将是一个字符串列表

large.txt - 要搜索的文本,“large”将是一个单个字符串

 with open('search.txt') as x: searchterms = x.readlines()
 with open('large.txt') as x: large = x.read()

我建议您按照HussainNagri在他的答案中提出的方法,迭代遍历searchterms以在large中查找匹配项:
for i in searchterms:
  if i in large:
    print i, " found in text"

现代计算机来说,大约75 kb的文本并不会对其造成太大的压力。 - VoronoiPotato
我同意...但这完全不是我在这里说的。我鼓励你在将某人的帖子下投票之前实际阅读一下,因为他们建议使用文件存储大量数据 - kevlar1818
这与问题无关,实际上并没有帮助他解决搜索信息的行为。 - VoronoiPotato
好的,但是由于原帖没有指定输入方法,我想提供一个很好的选择来高效地将数据输入到Python中(效率似乎是他的主要议程)。此外,我在我的帖子末尾仍然回答了问题 - kevlar1818
一旦加载到内存中,无论是在代码中还是在文件中声明,它的速度都是一样快的,而且这个答案在功能上等同于第一个发布的答案。我并不是想表现得很刻薄,只是我认为这不是一个非常有建设性的答案。如果您可以编辑它使其更有帮助,我会取消我的反对票。 - VoronoiPotato
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接