Python: как отсортировать значение словаря с помощью регулярных выражений - PullRequest
2 голосов
/ 11 апреля 2019

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

Вот мои файлы: file1.txt

file Marvel/GuardiansOfGalaxy 300 1
file DC/Batman 504 1
file GameOfThrones 900 0
file DC/Superman 200 1
file Marvel/CaptainAmerica 342 0

file2.txt

file Science/Biology 200 1
file Math/Calculus 342 0
file Psychology 324 1
file Anthropology 234 0
file Science/Chemistry 444 1

Это предполагаемый вывод:

Game of Thrones: 900
DC/Batman: 404
Science/Chemistry: 444
Marvel/CaptainAmerica 342
Math/Calculus 342
...

Вот так выглядит мой код. У меня проблемы с отображением данных в отсортированном виде на основе значения (третья вкладка) с помощью регулярных выражений. Функция чтения работает. Теперь все зависит от отображения отсортированного словаря:

def read():
    pattern = re.compile(r"file\.py (.+).*? (\d+) \d+")

    data_files = []
    for file in glob.glob("*.txt"):
        with open(file, 'r') as filenames:
            data_files.append(dict(pattern.findall(filenames.read())))
    return data_files

Здесь я попытался отсортировать значения из словаря, используя re.findall и map (int,), но я получил TypeError. Я не мог определить, где я ошибся. В этой части мне нужна помощь в основном:

def display(data_files):
    for lines in data_files:
        # print(lines)
        pattern_sort = re.findall(r"file\.py (.+).*? (\d+) \d+", data_files)
        print(sorted(lines, key=lambda x: (map(int, pattern_sort))))

Надеюсь, это имеет смысл. Спасибо!

Ответы [ 2 ]

1 голос
/ 11 апреля 2019

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

Обратите внимание, что мне пришлось изменить символ табуляции на |||, поскольку repl.it не позволяет мне использовать символ табуляции в файлах. Вам придется заменить ||| на \t в сценарии ниже.

Смотри, беги сюда

import glob
from collections import defaultdict, OrderedDict

d = defaultdict(list)

def read():
  for files in glob.glob('*.txt'):
    with open(files, 'r') as f:
      for line in f:
        r = line.rstrip('\n').split('|||')
        d[r[2]].append(r)

def display(d):
  od = OrderedDict(sorted(d.items(), reverse=True))
  for k,v in od.items(): print(k,v)

read()
display(d)

Вывод для приведенного выше сценария приведен ниже:

900 [['file', 'GameOfThrones', '900', '0']]
504 [['file', 'DC/Batman', '504', '1']]
444 [['file', 'Science/Chemistry', '444', '1']]
342 [['file', 'Marvel/CaptainAmerica', '342', '0'], ['file', 'Math/Calculus', '342', '0']]
324 [['file', 'Psychology', '324', '1']]
300 [['file', 'Marvel/GuardiansOfGalaxy', '300', '1']]
234 [['file', 'Anthropology', '234', '0']]
200 [['file', 'DC/Superman', '200', '1'], ['file', 'Science/Biology', '200', '1']]

Различные выходы

Изменение print(k,v) на другой формат дает вам другой результат, как вы отметили в комментариях ниже. Например:

print(k, [x[1] for x in v])

Это приводит к следующему:

900 ['GameOfThrones']
504 ['DC/Batman']
444 ['Science/Chemistry']
342 ['Marvel/CaptainAmerica', 'Math/Calculus']
324 ['Psychology']
300 ['Marvel/GuardiansOfGalaxy']
234 ['Anthropology']
200 ['DC/Superman', 'Science/Biology']
1 голос
/ 11 апреля 2019

Как сказал FailSafe , нет причины использовать regex для этого, поэтому я использовал split.Я добавлю regex решение этой проблемы позже, но вот как это сделать без regex.

import glob
from collections import namedtuple

# A lightweight object.
# Makes it easier to sort.
Entry = namedtuple("Entry", "name views")

def read():
    data_files = []
    for file in glob.glob("*.txt"):
        with open(file, 'r') as infile:
            for line in infile.read().splitlines():
                # For each line in the file

                # Split apart our line
                line = line.split(' ')
                # Create an Entry object with our name and views
                # and add it to our data_files.
                data_files.append(Entry(line[1], int(line[2])))
    return data_files
result = read()

# We want to sort based on views so return the views.
def sort_meth(x):
    return x.views
    # If you want to sort by views then name you can do
    # return (x.views, x.name)

# Sort our result
result.sort(key=sort_meth, reverse=True)
for entry in result: # Print each entry
  print(entry.name, entry.views)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...