I have 2 lists from a csv file.
column1 = ZIP codes
column2 = City Name
I have a string; that contains some random text, and possibly zip codes and cities names.
I want to check for each i if column1[i] & colmun2[i] are in the string.
I used this solution but that only checks if words from 1 list are in string. And doesn't returns position from the original list, so can't match on that after for column2.
I ended up using :
for i in range(39000):
if all(map(lambda w: w in text, (column1[i], column2[i]))):
print(column1[i], column2[i])
But for two 39000 words list, i'm @ around 0.30 seconds, isn't there any process that could go faster. This solution is twice faster (0.13 to 0.17sec), but only search for 1 word...
Any ideas ? Thanks
Edit reprocuctible example :
import pandas as pd
column_names = ["code_commune_insee","nom_de_la_commune", "code_postal","ligne_5","libelle_d_acheminement","coordonnees_gps"]
df = pd.read_csv("laposte_hexasmal.csv", names=column_names, delimiter=';')
column1 = df.code_postal.to_list()
column2 = df.nom_de_la_commune.to_list()
column1_short_version_example = ['48283', '43288', '84389', '403294', '84384', '88439']
column2_short_version_example = ['PARIS', 'Paris', 'London', 'Amsterdam', 'Dublin', 'Manchester']
text = 'Hello, yes your order is indeed confirmed for the 14th in our hotel neer PARIS 12, the zip code is 43288 or 75012, if you want to book a night in London two weeks after, we still have room avaible, the postal code for the hotel address is 45 road street 84389'
for i in range(len(column1)):
if all(map(lambda w: w in text, (column1[i], column2[i]))):
print(column1[i], column2[i])
The wanted result for short lists version is :
43288 Paris
84389 London
The wanted result for csv guiven file lists version is :
75012 PARIS 12
CodePudding user response:
You can loop directly over the items instead of the indices and use the built-in zip function to loop over both the lists simultaneously -
def op(): # this is your solution
collect = [] # I am collecting into a list instead of print for benchmark
for i in range(len(column1)):
if all(map(lambda w: w in text, (column1[i], column2[i]))):
collect.append((column1[i], column2[i]))
return collect
def zip_based(): # this is what I am proposing
collect = [] # I am collecting into a list instead of print for benchmark
for zipcode, city in zip(column1, column2):
if zipcode in text and city in text:
collect.append((zipcode, city))
return collect
Output YMMV, but I am seeing a ~3X speed-up -
%timeit op()
# 9.93 µs ± 618 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit zip_based()
# 3.01 µs ± 489 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
CodePudding user response:
you should try to iterate through the rows of your dataframe
#Suppose df is your dataframe with columns 'ZIP' and 'City'
#Suppose text is your string "that contains some random text, and possibly zip codes and cities names"
for index, row in df.iterrows():
if(any(row['ZIP'] in text, row['City'] in text)):
print(f"Row {index} : {row['ZIP']} and {row['City']}")