Как использовать подстановочный знак или регулярное выражение для нескольких строк - PullRequest
0 голосов
/ 18 июня 2019

У меня есть список названий SKU, и мне нужно разобрать сокращения в слова.

Сокращения отличаются по длине (2-5 символов), но соответствуют порядку фактического слова.

Пара примеров:

Имя SKU: «235 DSKTP 10LB» ----> «Рабочий стол»

SKU Имя: "222840 MSE 2oz" ----> "Мышь"

Другие примечания:

  1. Имена SKU - не все заглавные буквы, хотя я знаю, что это, вероятно, легче изменить с помощью метода .upper ()
  2. Список слов, которые мне нужно сопоставить, длинный (более 100 слов), поэтому, возможно, создание списка слов для сопоставления с шаблоном будет наиболее эффективным?

Я играл с регулярным выражением, но безрезультатно.

Есть ли регулярные выражения, похожие на d? E? S? K? T? O? P?

Ответы [ 3 ]

0 голосов
/ 18 июня 2019

Вы можете создать словарь, который связывает аббревиатуру с фактическим словом:

import re
names = ["235 DSKTP 10LB", "222840 MSE 2oz"]
abbrs = {'DSKTP':'Desktop', 'MSE':'Mouse'}
matched = [re.findall('(?<=\s)[a-zA-Z]+(?=\s)', i) for i in names]
result = ['N/A' if not i else abbrs.get(i[0], i[0]) for i in matched]

Выход:

['Desktop', 'Mouse']
0 голосов
/ 18 июня 2019

Поиск Расстояние Левенштейна - измеряет «сходство текста».

Источник Левенштейн-Реализация: https://en.wikibooks.org/wiki/Algorithm_Implementation

def levenshtein(s1, s2):
    # source: https://en.wikibooks.org/wiki/Algorithm_Implementation
    #               /Strings/Levenshtein_distance#Python
    if len(s1) < len(s2):
        return levenshtein(s2, s1)

    # len(s1) >= len(s2)
    if len(s2) == 0:
        return len(s1)

    previous_row = range(len(s2) + 1)
    for i, c1 in enumerate(s1):
        current_row = [i + 1]
        for j, c2 in enumerate(s2):
            insertions = previous_row[j + 1] + 1  
            deletions = current_row[j] + 1        
            substitutions = previous_row[j] + (c1 != c2)
            current_row.append( min(insertions, deletions, substitutions))
        previous_row = current_row

    return previous_row[-1]

Применительно к вашей проблеме:

skus = ["235 DSKTP 10LB","222840 MSE 2oz"]
full = ["Desktop", "Mouse", "potkseD"]

# go over all skus
for sku in skus:
    name = sku.split()[1].lower()       # extract name
    dist = []
    for f in full:                      # calculate all levenshtein dists to full names
                                        # you could shorten this by only using those
                                        # where 1st character is identicall
        dist.append( ( levenshtein(name.lower(),f.lower()),name,f) )

    print(dist)

    # get the minimal distance (beware if same distances occure)
    print( min( (p for p in dist), key = lambda x:x[0]) )

Выход:

# distances 
[(2, 'dsktp', 'Desktop'), (5, 'dsktp', 'Mouse'), (6, 'dsktp', 'potkseD')]

# minimal one
(2, 'dsktp', 'Desktop')

# distances
[(6, 'mse', 'Desktop'), (2, 'mse', 'Mouse'), (5, 'mse', 'potkseD')]

# minimal one
(2, 'mse', 'Mouse')

Если у вас есть фиксированное сопоставление, сядьте и создайте словарь сопоставления вручную один раз, и вы будете в восторге, пока не появится новый skus.

0 голосов
/ 18 июня 2019
import re
from collections import OrderedDict

data = '''
235 DSKTP 10LB
222840 MSE 2oz
1234 WNE 1L
12345 XXX 23L
RND PTT GNCH 16 OZ 007349012845
FRN SHL CNCH 7.05 OZ 007473418910
TWST CLNT 16 OZ 00733544
'''

words = ['Desktop',
'Mouse',
'Tree',
'Wine',
'Gnocchi',
'Shells',
'Cellentani']

def compare(sku_abbr, full_word):
    s = ''.join(c for c in full_word if c not in set(sku_abbr) ^ set(full_word))
    s = ''.join(OrderedDict.fromkeys(s).keys())
    return s == sku_abbr

for full_sku in data.splitlines():
    if not full_sku:
        continue
    for sku_abbr in re.findall(r'([A-Z]{3,})', full_sku):
        should_break = False
        for w in words:
            if compare(sku_abbr.upper(), w.upper()):
                print(full_sku, w)
                should_break = True
                break
        if should_break:
            break
    else:
        print(full_sku, '* NOT FOUND *')

Печать:

235 DSKTP 10LB Desktop
222840 MSE 2oz Mouse
1234 WNE 1L Wine
12345 XXX 23L * NOT FOUND *
RND PTT GNCH 16 OZ 007349012845 Gnocchi
FRN SHL CNCH 7.05 OZ 007473418910 Shells
TWST CLNT 16 OZ 00733544 Cellentani
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...