2015-08-18 5 views
2

Я хочу, чтобы быстрый метод pythonic дал мне счет в цикле. Я на самом деле слишком смущен, чтобы опубликовать мои решения, которые в настоящее время не работают.Python подсчет вхождений на несколько строк с использованием циклов

Учитывая образец из текстового файла структурированного следующим образом:

script7 BLANK INTERRUPTION script2 launch4.VBS script3 script8 launch3.VBS script5 launch1.VBS script6

Я хочу, чтобы подсчет всех времен сценария [у] сопровождается запуском [X]. Запуск имеет диапазон значений от 1 до 5, в то время как сценарий имеет диапазон 1-15.

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

script3 
launch1 
#count this 

script3 
launch2 
#count this 

script3 
launch3 
#count this 

script3 
launch4 
#count this 

script3 
launch4 
#count this 

script3 
launch5 
#count this 

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

+0

Просьба пример вывода вы пытаетесь достичь. – MattH

+0

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

ответ

1

Почему бы не использовать многострочные регулярные выражения - то сценарий становится:

import re 

# read all the text of the file, and clean it up 
with open('counts.txt', 'rt') as f: 
    alltext = '\n'.join(line.strip() for line in f) 

# find all occurrences of the script line followed by the launch line 
cont = re.findall('^script(\d)\nlaunch(\d+)\.VBS\n(?mi)',alltext) 

# accumulate the counts of each launch number for each script number 
# into nested dictionaries 
scriptcounts = {} 
for scriptnum,launchnum in cont: 
    # if we haven't seen this scriptnumber before, create the dictionary for it 
    if scriptnum not in scriptcounts: 
     scriptcounts[scriptnum]={} 
    # if we haven't seen this launchnumber with this scriptnumber before, 
    # initialize count to 0 
    if launchnum not in scriptcounts[scriptnum]: 
     scriptcounts[scriptnum][launchnum] = 0 
    # incremement the count for this combination of script and launch number 
    scriptcounts[scriptnum][launchnum] += 1 

# produce the output in order of increasing scriptnum/launchnum 
for scriptnum in sorted(scriptcounts.keys()): 
    for launchnum in sorted(scriptcounts[scriptnum].keys()): 
     print "script%s\nlaunch%s.VBS\n# count %d\n"%(scriptnum,launchnum,scriptcounts[scriptnum][launchnum]) 

Выход (в формате запрошенного) представляет собой, например:

script2 
launch1.VBS 
# count 1 

script2 
launch4.VBS 
# count 1 

script5 
launch1.VBS 
# count 1 

script8 
launch3.VBS 
# count 3 

re.findall() возвращает список всех совпадений - каждая ma tch - это список() частей шаблона, кроме (? mi), который является директивой, указывающей, что совпадение регулярных выражений работает по контурам строк \ n и соответствует нечувствительности к регистру. Шаблон регулярного выражения, как он есть, например. (\ d) 'вытаскивает цифру, следующую за сценарием/запуском, в совпадение - это может также легко включать «скрипт», будучи «(скрипт \ d)», аналогичным образом (запуск \ d + \. VBS) и для обработки этого варианта потребуется только печать.

НТН Barny

1

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

#!/usr/bin/env python3 

import re 
script_dict={} 
with open('infile.txt','r') as infile: 
    scriptre = re.compile(r"^script\d+$") 
    for line in infile: 
     line = line.rstrip() 
     if scriptre.match(line) is not None: 
      script_dict[line] = {} 

    infile.seek(0) # go to beginning 
    launchre = re.compile(r"^launch\d+\.[vV][bB][sS]$") 
    current=None 
    for line in infile: 
     line = line.rstrip() 
     if line in script_dict: 
      current=line 
     elif launchre.match(line) is not None and current is not None: 
      if line not in script_dict[current]: 
       script_dict[current][line] = 1 
      else: 
       script_dict[current][line] += 1 

print(script_dict) 
1

Вот мое решение, использующее defaultdict с счетчиками и regex with lookahead.

import re 
from collections import Counter, defaultdict 

with open('in.txt', 'r') as f: 
    # make sure we have only \n as lineend and no leading or trailing whitespaces 
    # this makes the regex less complex 
    alltext = '\n'.join(line.strip() for line in f) 

# find keyword script\d+ and capture it, then lazy expand and capture everything 
# with lookahead so that we stop as soon as and only if next word is 'script' or 
# end of the string 
scriptPattern = re.compile(r'(script\d+)(.*?)(?=script|\n?$)', re.DOTALL) 

# just find everything that matches launch\d+ 
launchPattern = re.compile(r'launch\d+') 

# create a defaultdict with a counter for every entry 
scriptDict = defaultdict(Counter) 

# go through all matches 
for match in scriptPattern.finditer(alltext): 
    script, body = match.groups() 
    # update the counter of this script 
    scriptDict[script].update(launchPattern.findall(body)) 

# print the results 
for script in sorted(scriptDict): 
    counter = scriptDict[script] 
    if len(counter): 
     print('{} launches:'.format(script)) 
     for launch in sorted(counter): 
      count = counter[launch] 
      print('\t{} {} time(s)'.format(launch, count)) 
    else: 
     print('{} launches nothing'.format(script)) 

Используя строку на regex101 (см ссылку выше) я получаю следующий результат:

script2 launches: 
    launch4 1 time(s) 
script3 launches nothing 
script5 launches: 
    launch1 1 time(s) 
script6 launches nothing 
script7 launches nothing 
script8 launches: 
    launch3 1 time(s) 
0

Вы можете использовать setdefault метод

код:

dic={} 
with open("a.txt") as inp: 
    check=0 
    key_string="" 
    for line in inp: 
     if check: 
      if line.strip().startswith("launch") and int(line.strip()[6])<6: 
       print "yes" 
       dic[key_string]=dic.setdefault(key_string,0)+1 
      check=0 
     if line.strip().startswith("script"): 
      key_string=line.strip() 
      check=1 

Для вашего ввода вход будет

выход:

{"script3":6} 
Смежные вопросы