Python-在两个字符串变得不同时查找
我试图从产品名称列表中提取产品线名称。这将是产品名称的一个子集,并且总是从字符串的开头到名称列出产品线中的变化(如大小、颜色等)的任意点。这对人来说非常容易做到,但数据量要求实现自动化 Ex数据:Python-在两个字符串变得不同时查找,python,python-2.7,parsing,Python,Python 2.7,Parsing,我试图从产品名称列表中提取产品线名称。这将是产品名称的一个子集,并且总是从字符串的开头到名称列出产品线中的变化(如大小、颜色等)的任意点。这对人来说非常容易做到,但数据量要求实现自动化 Ex数据: item_id description 100 SomeBrand Medical Jackets Blue SM 101 SomeBrand Medical Jackets Blue M 200 Acme Gloves
item_id description
100 SomeBrand Medical Jackets Blue SM
101 SomeBrand Medical Jackets Blue M
200 Acme Gloves Pink X Large
201 Acme Gloves Pink Small 100 Pack
202 Acme Gloves White X Large
203 Acme Gloves White Small
期望输出:
item_id family
100 SomeBrand Medical Jackets Blue
101 SomeBrand Medical Jackets Blue
200 Acme Gloves Pink
201 Acme Gloves Pink
202 Acme Gloves White
203 Acme Gloves White
方法:
遍历行,遍历每个描述字符串,将每次与最后一项的描述进行比较,如果描述发生更改,则停止。当它从最后一个描述及其超过10个字符更改为字符串时,它会备份一个位置并调用该姓氏。它也适用于上一个项目,因为它是族中的第一个项目,除了一个不匹配的字符串外,没有其他可比较的项目。对于每一个新的描述,我都要确保它与上一个使用SequenceMatcher的描述非常相似,以便在数据进入新的产品系列时重置
我愿意接受关于更好方法的建议。我的代码工作不好,在字符串的末尾留下了工件。实际数据千差万别,但大多数产品线的描述都有一个共同的起点,应该能够提取这些起点来形成家族名称
代码(Win10上的Python 2.7):
我会解释我的想法:
您设置了一个阈值,这意味着至少有多少个字符应该重叠以定义一个新的系列,并假设每个产品都有一个系列。
通过这样做,您可以将每个新产品存储为一个新的系列。当一个新产品与一个系列重叠超过阈值个字符时,您会收缩该系列名称,以便这两个产品现在都属于该系列
products = [
"SomeBrand Medical Jackets Blue SM ",
"SomeBrand Medical Jackets Blue M",
"Acme Gloves Pink X Large",
"Acme Gloves Pink Small 100 Pack",
"Acme Gloves White X Large",
"Acme Gloves White Small"
]
families = list()
ifam = list() #index of the family
threshold = 15 #at least 15 characters should be equals
for prod in products:
if len(prod) < threshold: continue
check = False
for j in range(len(families)):
fam = families[j]
if prod[:threshold] == fam[:threshold]:
check = True #product has an already existed category
for i in range(min(len(prod),len(fam))):
if prod[i] != fam[i]:
families[j] = fam[:i] #keep only the same characters
ifam.append(j) #product[i] is in the j family
break
ifam.append(j)
break
if not check:
families.append(prod) #this product will be used for a category
#let me see the families
for i in range(len(products)):
print("product: \"%s\" is in the family: \"%s\"" % (products[i],families[ifam[i]]))
产品=[
“SomeBrand医疗夹克蓝色SM”,
“SomeBrand医疗夹克蓝色M”,
“Acme手套粉色X大号”,
“Acme手套粉色小100包”,
“Acme手套白色X大号”,
“Acme手套白色小”
]
族=列表()
ifam=列表()#族的索引
阈值=15#至少应等于15个字符
对于产品中的产品:
如果len(prod)<阈值:继续
检查=错误
对于范围内的j(len(族)):
fam=家庭[j]
如果产品[:阈值]==fam[:阈值]:
check=True#产品已存在类别
对于范围内的i(最小值(len(prod),len(fam)):
如果prod[i]!=fam[i]:
族[j]=fam[:i]#只保留相同的字符
ifam.append(j)#产品[i]属于j族
打破
ifam.append(j)
打破
如果没有,请检查:
families.append(prod)#此产品将用于一个类别
#让我看看这些家庭
对于范围内的i(len(产品)):
打印(“产品:\%s\”在系列:\%s\”“%中(产品[i],系列[ifam[i]]))
如果要使用此代码,请记住,您必须选择哪个阈值更适合您,以及如何处理名称短于阈值的产品您可以使用
itertools
中的pairwise()
import itertools
brands = ["SomeBrand Medical Jackets Blue SM ",
"SomeBrand Medical Jackets Blue M",
"Acme Gloves Pink X Large",
"Acme Gloves Pink Small 100 Pack",
"Acme Gloves White X Large",
"Acme Gloves White Small"]
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = itertools.tee(iterable)
next(b, None)
return zip(a, b)
table = []
for pair in pairwise(brands):
stack = ""
for x, y in zip(pair[0], pair[1]):
if x == y:
stack += x
else:
if stack:
trunk = stack
break
table.append((trunk.rstrip(), pair[0]))
print(table)
这就产生了
[
('SomeBrand Medical Jackets Blue', 'SomeBrand Medical Jackets Blue SM '),
('SomeBrand Medical Jackets Blue', 'SomeBrand Medical Jackets Blue M'),
('Acme Gloves Pink', 'Acme Gloves Pink X Large'),
('Acme Gloves', 'Acme Gloves Pink Small 100 Pack'),
('Acme Gloves White', 'Acme Gloves White X Large')
]
对不起,我得问一下:Python 2已经死了。对于一般的文本解析来说,这也是一个坏主意(因为很难让它正确地处理非ASCII,而且当您这样做时,它比Py3慢得多,内存更密集)。你为什么要在里面写新代码?
[
('SomeBrand Medical Jackets Blue', 'SomeBrand Medical Jackets Blue SM '),
('SomeBrand Medical Jackets Blue', 'SomeBrand Medical Jackets Blue M'),
('Acme Gloves Pink', 'Acme Gloves Pink X Large'),
('Acme Gloves', 'Acme Gloves Pink Small 100 Pack'),
('Acme Gloves White', 'Acme Gloves White X Large')
]