Как отсортировать список строк по части 3-й строки? - PullRequest
0 голосов
/ 29 марта 2019

Начинающий здесь:

Я пытаюсь отсортировать список псевдонимов по соответствующим странам в одной строке.Они приходят в следующем формате:

FODORGBR + HU-Szombathely-2

ZSOLDPTE + HU-Debrecen-3

THAUSKTR + DE-Herzogenaurach-1

WRIGHNIL + UK-SuttonColdfield-2

KUROTADR + SK-KysuckeNoveMesto-1

KLERNMTT + DE-Herzogenaurach-1

BIRKNJHA + DE-Erlangen-111

CANECVAD + SK-KysuckeNoveMesto-1

MALDESND + DE-Herzogenaurach-1

Я хочу отсортировать его по инициалам страны (таким как HU, DE и т. Д.) С подписью.Итак, что-то вроде:

DE:

THAUSKTR

KLERNMTT

BIRKNJHA

MALDESND


HU:

FODORGBR 

ZSOLDPTE

Это то, что я придумал для определения стран, но я не могу понять, как отсортировать все строки с ним.

fw = open("NameList.txt")
for line_fw in fw:
    if not line_fw.strip():
        continue
    cross = line_fw.find("+")
    country = line_fw[cross+2:cross+4]

Ответы [ 4 ]

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

Ниже приведен фрагмент, который поможет вам:

sample = '''
FODORGBR + HU-Szombathely-2

ZSOLDPTE + HU-Debrecen-3

THAUSKTR + DE-Herzogenaurach-1

WRIGHNIL + UK-SuttonColdfield-2

KUROTADR + SK-KysuckeNoveMesto-1

KLERNMTT + DE-Herzogenaurach-1

BIRKNJHA + DE-Erlangen-111

CANECVAD + SK-KysuckeNoveMesto-1

MALDESND + DE-Herzogenaurach-1
'''
def find_between( s, first, last ):
    try:
        start = s.index( first ) + len( first )
        end = s.index( last, start )
        return s[start:end]
    except ValueError:
        return ""

data = sample.splitlines()

elements = {}
for indv in data:
    code = find_between(indv,"+","-").strip()
    value = find_between(indv,"","+").strip()
    if code != '' and code in elements:
        values = []
        values.append(value)
        values.extend(elements[code])
        values = list(filter(None, values))
        values.sort()
        elements[code] = values
    elif code != '':
        values = []
        values.append(value)
        elements[code] = values

print(elements)

Выход: {'HU': ['FODORGBR', 'ZSOLDPTE'], 'DE': ['BIRKNJHA', 'KLERNMTT', 'MALDESND', 'THAUSKTR'], 'UK': ['WRIGHNIL'], 'SK' : ['CANECVAD', 'KUROTADR']}

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

Использование re.search и collections.defaultdict:

import re
from collections import defaultdict

d = defaultdict(list)
with open('NameList.txt') as fw:
    for line in fw:
        code = re.search(' (\w{2})-', line).group(1)
        nick = re.search('(\w{8}) +', line).group(1)
        d[code].append(nick)

Вывод:

defaultdict(list,
            {'DE': ['THAUSKTR', 'KLERNMTT', 'BIRKNJHA', 'MALDESND'],
             'HU': ['FODORGBR', 'ZSOLDPTE'],
             'SK': ['KUROTADR', 'CANECVAD'],
             'UK': ['WRIGHNIL']})
0 голосов
/ 29 марта 2019

Ваш код для поиска названий стран выглядит просто отлично. Один совет при работе с файлами: используйте оператор with - вместо open и close. При использовании open, и возникает ошибка перед вызовом close, возможно, файл неправильно закрыт, что может испортить все возможные вещи. with закрывает файл независимо от того, что происходит внутри соответствующего блока кода (он работает аналогично try - finally, для получения дополнительной информации см. Ссылку выше). Итак, вот так:

with open('NameList.txt', 'r') as fw:
    for line_fw in fw:
        ...

гарантируется, что файл всегда будет закрыт. Кстати, вместо использования line.find('+'), вы можете просто использовать line.split('+'), который убирает всю часть среза строки.

Теперь к вашему вопросу: здесь есть несколько возможностей. Самым простым будет определение списка для каждой страны и добавление соответствующих имен в правильный список:

de = []
hu = []
uk = []
sk = []

with open('NameList.txt', 'r') as fw:
    for line_fw in fw:
        if not line_fw.strip():
            continue
        country = line_fw.split('+')[1].split('-')[0].strip()
        nickname = line_fw.split('+')[0]
        if country == 'DE':
            de.append(nickname)
        elif country == 'HU':
            hu.append(nickname)
        elif country == 'UK':
            uk.append(nickname)
        else:
            sk.append(nickname)

это вернет список для каждой страны, содержащий соответствующие псевдонимы. Как видите, это очень неуклюже и долго. Более элегантное решение - использование словаря со странами в качестве ключей и списка имен в качестве значений:

d = {}

with open('NameList.txt', 'r') as fw:
    for line_fw in fw:
        if not line_fw.strip():
            continue
        country = line_fw.split('+')[1].split('-')[0].strip()
        nickname = line_fw.split('+')[0].strip()
        try:
            d[country].append(nickname)  # if country already exists in d, append the nickname
        except KeyError:
            d[country] = [nickname]  # if country doesn't exist in d, make a new entry

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

{'HU': ['FODORGBR', 'ZSOLDPTE'], 'DE': ['THAUSKTR'], 'UK': ['WRIGHNIL']}

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

Наконец, если я правильно понял, вы хотите записать свои результаты в новый файл или хотя бы распечатать их. Допустим, у вас есть словарь вышеуказанной формы. Просто переберите его ключи с помощью for k in d:, добавьте несколько новых строк ('\n') между ними и используйте join, чтобы преобразовать списки в одну строку с символами новой строки между всеми элементами:

for k in d:
    print(k + ':\n' + '\n'.join(d[k]) + '\n')

который напечатает:

HU:
FODORGBR 
ZSOLDPTE 

DE:
THAUSKTR 

UK:
WRIGHNIL 

добавив with open(outputfile, 'w') as f: и заменив print на f.write, вы можете легко записать это в новый файл.

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

Сначала разбейте список на " " и используйте operator.itemgetter для перебора последнего элемента списка.

Или замените -1 в itemgetter на 3, если код страны всегда является третьим элементомв списке.

from operator import itemgetter

x = ["FODORGBR + HU-Szombathely-2","ZSOLDPTE + HU-Debrecen-3","THAUSKTR + DE-Herzogenaurach-1",
"WRIGHNIL + UK-SuttonColdfield-2","KUROTADR + SK-KysuckeNoveMesto-1","KLERNMTT + DE-Herzogenaurach-1",
"BIRKNJHA + DE-Erlangen-111","CANECVAD + SK-KysuckeNoveMesto-1","MALDESND + DE-Herzogenaurach-1"]

new_list = [i.split() for i in x]
new_list.sort(key=itemgetter(-1))

print([" ".join(i) for i in new_list])

Вывод:

['BIRKNJHA + DE-Erlangen-111', 'THAUSKTR + DE-Herzogenaurach-1', 'KLERNMTT + DE-Herzogenaurach-1', 'MALDESND + DE-Herzogenaurach-1', '
ZSOLDPTE + HU-Debrecen-3', 'FODORGBR + HU-Szombathely-2', 'KUROTADR + SK-KysuckeNoveMesto-1', 'CANECVAD + SK-KysuckeNoveMesto-1', 'WRI
GHNIL + UK-SuttonColdfield-2']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...