Python - найти позицию индекса первого появления списка строк в строке - PullRequest
1 голос
/ 07 марта 2019

Я хотел бы найти в некотором тексте индекс первого вхождения набора строк (скажем, "->" или "--x" или "--XX") после того, как нашел, мне нужно знатьгде начальная позиция найденной строки и конкретная найденная строка (точнее, длина идентифицированной строки)

Это то, что у меня есть пока ... но этого недостаточно.Пожалуйста помоги.

arrowlist = {"->x","->","->>","-\","\\-","//--","->o","o\\--","<->","<->o"}
def cxn(line,arrowlist):
   if any(x in line for x in arrowlist):
      print("found an arrow {} at position {}".format(line.find(arrowlist),2))
   else:
      return 0 

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

Спасибо!

Ответы [ 4 ]

1 голос
/ 07 марта 2019

Следуя логике вашего примера, это было наиболее целесообразным способом найти «первую» подходящую стрелку и распечатать ее местоположение. Однако порядок наборов не FIFO, поэтому, если вы хотите сохранить порядок, я бы предложил заменить список вместо набора для arrowlist, чтобы сохранить порядок.

    arrowlist = {"->x","->", "->>", "-\\", "\\-","//--","->o","o\\--","<->","<->o"}
    def cxn(line, arrowlist):
       try:
           result = tuple((x, line.find(x)) for x in arrowlist if x in line)[0]
           print("found an arrow {} at position {} with length {}".format(result[0], result[1], len(result[0])))

       # Remember in general it's not a great idea to use an exception as
       # broad as Exception, this is just for example purposes.
       except Exception:
          return 0

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

arrowlist = {"->x","->", "->>", "-\\", "\\-","//--","->o","o\\--","<->","<->o"}

def cxn(line, arrowlist):
   try:
       # key first sorts on the position in string then shortest length 
       # to account for multiple arrow matches (i.e. -> and ->x)
       result = sorted([(x, line.find(x)) for x in arrowlist if x in line], key=lambda r: (r[1],len(r[0])))[0]
       # if you would like to match the "most complete" (i.e. longest-length) word first use:
       # result = sorted([(x, line.find(x)) for x in arrowlist if x in line], key=lambda r: (r[1], -len(r[0])))[0]
       print("found an arrow {} at position {} with length {}".format(result[0], result[1], len(result[0])))

   except Exception:
      return 0

Или, если у вас есть доступ к стандартной библиотеке, вы можете использовать operator.itemgetter для почти того же эффекта и получить эффективность от меньшего количества вызовов функций:

from operator import itemgetter

arrowlist = {"->x","->", "->>", "-\\", "\\-","//--","->o","o\\--","<->","<->o"}

def cxn(line, arrowlist):
   try:
       # key first sorts on the position in string then alphanumerically 
       # on the arrow match (i.e. -> and ->x matched in same position
       # will return -> because when sorted alphanumerically it is first)
       result = sorted([(x, line.find(x)) for x in arrowlist if x in line], key=(itemgetter(1,0)))[0]
       print("found an arrow {} at position {} with length {}".format(result[0], result[1], len(result[0])))

   except Exception:
      return 0

*** ПРИМЕЧАНИЕ. Я использую несколько иной список стрелок, чем в вашем примере, только потому, что приведенный вами, похоже, не соответствует форматированию кода по умолчанию (вероятно, из-за проблем с закрытием цитаты). Помните, что вы можете добавить строку с 'r' следующим образом: r"Text that can use special symbols like the escape \and\ be read in as a 'raw' string literal\". См. Этот вопрос для получения дополнительной информации о необработанных строковых литералах.

1 голос
/ 07 марта 2019

Вы могли бы сделать что-то вроде

count = 0
for item in arrowlist:
    count += 1
    if item in line:
        print("found an arrow {} at position {}".format(item,count))
1 голос
/ 07 марта 2019

Мне нравится это решение, вдохновленное этим постом:

Как использовать повторяющиеся объекты в понимании списка

import re

arrowlist = ["xxx->x", "->", "->>", "-\"","\\-"," // --","x->o", "-> ->"]

lines = ["xxx->x->->", "-> ->", "xxx->x", "xxxx->o"]

def filterPick(list,filter):
    return [(m.group(), item_number, m.start()) for item_number,l in enumerate(list) for m in (filter(l),) if m]


if __name__ == '__main__':

    searchRegex = re.compile(r''+ '|'.join(arrowlist) ).search
    x = filterPick(lines, searchRegex)
    print(x)

Вывод показывает:

[('xxx->x', 0, 0), ('->', 1, 0), ('xxx->x', 2, 0), ('x->o', 3, 3)]

Первый номер - индекс списка, а второй - начальный индекс строки.

0 голосов
/ 14 марта 2019

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

arrowlist = ["xxx->x", "->", "->>", "xxx->x","x->o", "xxx->"]
doc =""" @startuml
    n1 xxx->xx n2 : should not find
    n1 ->> n2 : must get the third arrow
    n2  xxx-> n3 : last item
    n3   -> n4 : second item
    n4    ->> n1 : third item"""

def checkForArrow(arrows,line):
    for a in arrows:
        words = line.split(' ')
        for word in words:
            if word == a:
                return(arrows.index(a),word,line.index(word))

for line in iter(doc.splitlines()):
    line = line.strip()
    if line != "":
        print (checkForArrow(arrowlist,line))

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

None
None
(2, '->>', 3)
(5, 'xxx->', 4)
(1, '->', 5)
(2, '->>', 6)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...