从列表中删除数字(如果未包含在其他列表的子字符串中)

时间:2018-11-02 01:35:49

标签: python pandas lambda apply psql

这是我的情况:

我有一个产品名称列表,例如:
BLUEAPPLE, GREENBUTTON20, 400100DUCK20(len = 9000)
以及官方商品名称列表,例如:
BLUEAPPLE, GREENBUTTON, 100DUCK。 (len = 2700)

由于我要对产品(商品)应用模糊字符串匹配,因此我想从产品名称中去除不必要的数字,但要保留正式商品名称中表示的数字。

我想出了一个解决方案,但问题是它非常运行缓慢。

def remove_nums(product):
    if bool(re.search('\d'), product):
        for item in item_nums_list:
            if item in product_name:
                substrings = [u for x in product_name.split(item) for u in (x, item)][:-1]
                no_num_list = [re.sub('(\d+)', '', substring) if substring not in item else substring for substring in substrings]
                return ''.join(no_num_list)
        return re.sub('(\d+)', '', product)
    else:
        return product

示例:

product_name = '400100DUCK20'
item = '100DUCK'
substrings = ['400','100DUCK','20']
no_num_list = ['','100OG','']
returns '100DUCK'

此功能已映射,因此可以遍历产品列表中的每个产品。

我一直在试图找到一种在这里使用lambda的方法,映射,应用等,但是我无法完全解决。用直线列表或熊猫来完成我尝试做的事情的最有效的方法是什么?另外,我从postgres数据库中获得这些产品和产品列表,因此,如果您认为在psql中进行操作会更快,那我就走这条路线。

2 个答案:

答案 0 :(得分:1)

difflib.get_close_matches()至少将帮助清理您的代码,并且可能会更快地运行。

import difflib
p_names = ['BLUEAPPLE', 'GREENBUTTON20', '400100DUCK20']
i_names = ['BLUEAPPLE', 'GREENBUTTON', '100DUCK']
for p in p_names:
    print(difflib.get_close_matches(p, i_names))

>>> 
['BLUEAPPLE']
['GREENBUTTON']
['100DUCK']
>>> 

仍然会有很多比较,它必须将p_names中的每个字符串与i_names中的每个字符串进行匹配。


类似于使用正则表达式查找匹配项的方法:

import re
for p in p_names:
    for i in i_names:
        if re.search(i, p):
            print(i)
            # stop looking
            break

答案 1 :(得分:1)

尝试一下:

def remove_nums(product):
    if re.search('\d', product):
        for item in item_nums_list:
            if item in product:
                return item
        return re.sub('(\d+)', '', product)
else:
    return product

此外,请确保您使用的是普通的python解释器。 IPython和其他具有调试功能的解释器比常规解释器慢很多。

您可能想考虑先进行一些设置操作。这是一个小例子:

product_set = set(product_list)
item_number_set = set(item_number_list)

# these are the ones that match straight away
product_matches = product_set & item_number_set

# now we can search through the substrings of ones that don't match
non_matches = product_set - item_number_set
for product in non_matches:
    for item_number in item_number_set:
        if item_number in product:
            product_matches.add(product)
            break

# product_matches is now a set of all unique codes contained in both lists by "fuzzy match"
print(product_matches)

您可能会失去它们出现的顺序,但是也许您可以找到一种方法来对其进行修改以供使用。