【问题标题】:Remove numbers from list, if not contained in substring of other list从列表中删除数字,如果不包含在其他列表的子字符串中
【发布时间】:2018-11-02 01:35:48
【问题描述】:

这是我的情况:

我有一个产品名称列表,例如:
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 中执行此操作会更快,我会走这条路。

【问题讨论】:

  • 举个例子,你为什么不直接返回item
  • 不幸的是,由于我匹配的产品和项目的性质,退回项目会导致很多误报。例如:COLA100(产品)将与A10(官方项目)匹配,而实际上它们不应该匹配。我稍后应用的模糊字符串匹配有望纠正这个问题。

标签: python pandas lambda apply psql


【解决方案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

【讨论】:

    【解决方案2】:

    试试这个:

    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)
    

    你有点失去了它们出现的顺序,但也许你可以找到一种方法来修改它以供你使用。

    【讨论】:

    • 很遗憾,如果商品在产品名称中,我不能只返回“商品”。在开始这个过程之前,我确实摆脱了完全匹配,所以我需要找到一种不同的优化方式。
    猜你喜欢
    • 1970-01-01
    • 2017-11-27
    • 1970-01-01
    • 1970-01-01
    • 2015-04-23
    • 1970-01-01
    • 2021-12-31
    • 1970-01-01
    • 2018-11-05
    相关资源
    最近更新 更多