Python сравнить частичную строку в списке друг с другом - PullRequest
3 голосов
/ 02 февраля 2020

Я пытаюсь написать код для сравнения каждой строки в списке друг с другом и затем сгенерировать ее регулярное выражение для сходства

list = ["LONDON-UK-L16-N1",
        "LONDON-UK-L17-N1",
        "LONDON-UK-L16-N2",
        "LONDON-UK-L17-N2",
        "PARIS-France-L16-N2"]

Я пытаюсь получить вывод, как показано ниже

LONDON-UK-L(16|17)-N(1|2)

это возможно? спасибо

Обновление: просто чтобы было понятно, что я пытаюсь ввести: список или строки. Действие: сравнить элементы списка друг с другом и проверить на сходство (чтобы исправить это первая группа строки), и используйте regex для любой другой не похожей части элемента, поэтому вместо элементов мы можем иметь один выход (используя regex): regex для сопоставления с не похожим

input: tez15-3-s1-y2 tez15-3-s2-y2 bro40-55-s1-y2

выход: tez15-3-s (1 | 2) -y2, bro40-55-s1-y2

Ответы [ 4 ]

3 голосов
/ 02 февраля 2020

Из вашего вопроса не совсем понятно, в чем именно заключается проблема. Поскольку данные, которые вы привели в качестве примера, согласованы и хорошо упорядочены, эту проблему можно легко решить, просто разделив элементы в списке и распределив их по категориям.

loc_list = ["LONDON-UK-L16-N1", "LONDON-UK-L17-N1", "LONDON-UK-L16-N2", 
            "LONDON-UK-L16-N2", "PARIS-France-L16-N2"]

split_loc_list = [location.split("-")  for location in loc_list]

locs = {}

for loc in split_loc_list:
    locs.setdefault("-".join(loc[0:2]), {}).\
                        setdefault("L", set()).add(loc[2].strip("L"))

    locs.setdefault("-".join(loc[0:2]), {}).\
                        setdefault("N", set()).add(loc[3].strip("N"))

for loc, vals in locs.items():
    L_vals_sorted = sorted(list(map(int,vals["L"])))
    L_vals_joined = "|".join(map(str,L_vals_sorted))

    N_vals_sorted = sorted(list(map(int,vals["N"])))
    N_vals_joined = "|".join(map(str,N_vals_sorted))

    print(f"{loc}-L({L_vals_joined})-N({N_vals_joined})")

выведет:

LONDON-UK-L(16|17)-N(1|2)
PARIS-France-L(16)-N(2)

Поскольку здесь было только два тега ("L" и "N"), я просто записал их в код. Если существует много возможных тегов, то вы можете вырезать любую букву, используя:

import re
split = re.findall('\d+|\D+', loc[2])
key, val = split[0], split[1]
locs.setdefault("-".join(loc[0:2]), {}).\
                        setdefault(key, set()).add(val)

Затем выполните итерацию по всем тегам вместо простого извлечения «L» и «N» во втором l oop.

1 голос
/ 03 февраля 2020

Я публикую эту новую (вторую) реализацию этой проблемы, думаю, что она более точна и, надеюсь, будет полезна:

import re 

data = [
  'LONDON-UK-L16-N1',
  'LONDON-UK-L17-N1',
  'LONDON-UK-L16-N2',
  'LONDON-UK-L17-N2',
  'LONDON-UK-L18-N2',
  'PARIS-France-L16-N2',
]

def merge(data):
  data.sort()
  data = [y for y in [x.split('-') for x in data]]

  for col in range(len(data[0]) - 1, -1, -1):
    result = []

    def add_result():
      result.append([])
      if headstr:
        result[-1] += headstr.split('-')
      if len(list(findnum)) > 1:
        result[-1] += [f'{findstr}({"|".join(sorted(findnum))})']
      elif len(list(findnum)) == 1:
        result[-1] += [f'{findstr}{findnum[0]}']
      if tailstr:
        result[-1] += tailstr.split('-')

    _headstr = lambda x, y: '-'.join(x[:y])
    _tailstr = lambda x, y: '-'.join(x[y + 1:])
    _findstr = lambda x: re.findall('(\D+)', x)[0] if re.findall('(\D+)', x) else ''
    _findnum = lambda x: re.findall('(\d+)', x)[0] if re.findall('(\d+)', x) else ''

    headstr = _headstr(data[0], col)
    tailstr = _tailstr(data[0], col)
    findstr = _findstr(data[0][col])
    findnum = []

    for row in data:
      if headstr + findstr + tailstr != _headstr(row, col) + _findstr(row[col]) + _tailstr(row, col):
        add_result()
        headstr = _headstr(row, col)
        tailstr = _tailstr(row, col)
        findstr = _findstr(row[col])
        findnum = []
      if _findnum(row[col]) not in findnum:
        findnum.append(_findnum(row[col]))

    else:
        add_result()

    data = result[:]

  return ['-'.join(x) for x in result]

print(merge(data))  # ['LONDON-UK-L(16|17)-N(1|2)', 'LONDON-UK-L18-N2', 'PARIS-France-L16-N2']
1 голос
/ 02 февраля 2020

Я реализовал следующее решение:

import re 

data = [
  'LONDON-UK-L16-N1',
  'LONDON-UK-L17-N1',
  'LONDON-UK-L16-N2',
  'LONDON-UK-L16-N2',
  'PARIS-France-L16-N2'
]

def deconstruct(data):
  data = [y for y in [x.split('-') for x in data]]
  result = dict()

  for x in data:
    pointer = result

    for y in x:
      substr = re.findall('(\D+)', y)
      if substr:
        substr = substr[0]
        if not substr in pointer:
          pointer[substr] = {0: set()}
        pointer = pointer[substr]

      substr = re.findall('(\d+)', y)
      if substr:
        substr = substr[0]
        pointer[0].add(substr)

  return result

def construct(data, level=0):
  result = []

  for key in data.keys():
    if key != 0:
      if len(data[key][0]) == 1:
        nums = list(data[key][0])[0]
      elif len(data[key][0]) > 1:
        nums = '(' + '|'.join(sorted(list(data[key][0]))) + ')'
      else:
        nums = ''

      deeper_result = construct(data[key], level + 1)
      if not deeper_result:
        result.append([key + nums])
      else:
        for d in deeper_result:
          result.append([key + nums] + d)

  return result if level > 0 else ['-'.join(x) for x in result]

print(construct(deconstruct(data)))
# ['LONDON-UK-L(16|17)-N(1|2)', 'PARIS-France-L16-N2']
0 голосов
/ 02 февраля 2020

Не используйте «список» в качестве имени переменной ... это зарезервированное слово.

import re

lst = ['LONDON-UK-L16-N1', 'LONDON-UK-L17-N1', 'LONDON-UK-L16-N2', 'LONDON-UK-L16-N2', 'PARIS-France-L16-N2']

def check_it(string):
    return re.search(r'[a-zA-Z\-]*L(\d)*-N(\d)*', string)

[check_it(x).group(0) for x in lst]

выведет:

['LONDON-UK-L16-N1',
 'LONDON-UK-L17-N1',
 'LONDON-UK-L16-N2',
 'LONDON-UK-L16-N2',
 'PARIS-France-L16-N2']

Оттуда посмотрите на группы и определите группу, чтобы покрыть части, которые вы хотите использовать для сходства.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...