LINUX.ORG.RU

Не удается вывести все значения из словаря на Python

 ,


0

1

Приветствую. Задача распарсить файл «/usr/share/X11/xkb/rules/base.lst», в котором находится список доступных раскладок клавиатуры, вариантов языка раскладки, моделей клавиатур и т.д. В принципе, получить желаемое удалось, однако при попытке вывести список всех значений из словаря с вариантами, выводятся далеко не все (из 479 выводятся всего 331). Подскажите пожалуйста, где косяк в коде? Может быть есть другой способ парсинга этого файла и разбивки его на списки по раскладкам, вариантом и т.д?

#!/usr/bin/env python3

layouts = {}
options = {}
variants = {}
models = {}
current = None

with open('/usr/share/X11/xkb/rules/base.lst') as f:
    for line in f:
        if len(line) < 2:
            continue
        one, two = line.strip().split(maxsplit=1)
        if one == '!':
            if two == 'layout':
                current = layouts
            elif two == 'option':
                current = options
            elif two == 'variant':
                current = variants
            elif two == 'model':
                current = models
        elif current is not None:
            current[one] = two

for key, values in variants.items():
    print(values)

Ответ на: комментарий от CrX

ну там не столько дублей же (у меня во всяком случае).

Все таки ТС-у наверное лучше почетче сформулировать что именно он хочет сделать. В процессе формулировки и сам поймет что не так;-)

AntonI ★★★★★
()
Ответ на: комментарий от AntonI

Все таки ТС-у наверное лучше почетче сформулировать что именно он хочет сделать

Мне нужно распарсить этот файл, и вынести в отдельные списки раскладки, варианты, модели клавиатуры и опции (комбинации переключения раскладок). При чем самое проблематичное это варианты, поскольку там мало того что описание и значение, так ещё и в описании стоит префикс языка раскладки, которому этот вариант соответствует. С выше описанным кодом я могу это сделать так:

#!/usr/bin/env python3

layouts = {}
options = {}
variants = {}
models = {}
current = None

with open('/usr/share/X11/xkb/rules/base.lst') as f:
    for line in f:
        if len(line) < 2:
            continue
        one, two = line.strip().split(maxsplit=1)
        if one == '!':
            if two == 'layout':
                current = layouts
            elif two == 'option':
                current = options
            elif two == 'variant':
                current = variants
            elif two == 'model':
                current = models
        elif current is not None:
            current[one] = two

for key, values in variants.items():
    value = values.split(":")[0]
    print(value)
То есть у меня есть словарь variants, у значений которого также стоит префикс. Я могу отсечь все что после префикса (то есть после двоеточия), и таким образом сопоставить конкретный вариант с языком выбранной раскладки. Но вся проблема в том, что в словарь с вариантами загружаются далеко не все варианты. Выше написали почему, и я не знаю как обойти эту проблему.

Sunderland93 ★★★★★
() автор топика
Ответ на: комментарий от AntonI

ну там не столько дублей же (у меня во всяком случае).

Достаточно ведь одного. На каждой итерации, когда встречается «legacy» в переменной one, происходит variants["legacy"] = two, где two — прочитанное сейчас наименование раскладки. Предыдущее значение заменяется новым.

P.S. @Sunderland93, см. выше.

Как обойти проблему: ну например, можно сделать не строки, а списки строк в качестве значений для variants.

Либо, разбивать two по двоеточию, если оно там есть, и первую половинку добавлять к one (ну например через пробел в конец), а вторую присваивать переменной two.

CrX ★★★★★
()
Последнее исправление: CrX (всего исправлений: 3)
Ответ на: комментарий от CrX

Каждый дубль это всего лишь минус одна строка (актуальным остается последнее значение)? А у ТС теряется 30%

можно сделать не строки, а списки строк в качестве значений для variants.

да, через

variants.setdefault(one, []).append(two)

или set вместо списка

AntonI ★★★★★
()
Ответ на: комментарий от Sunderland93

Я бы для начала переписал это как

table, block = {}, None

with open('/usr/share/X11/xkb/rules/base.lst') as f:
    for line in f:
        if len(line) < 2: continue
        one, two = line.strip().split(maxsplit=1)
        if one == '!': block = table.setdefault(two, {})
        elif block is not None: block.setdefault(one, []).append(two)

потому что все эти свитчи это ппц;-)

AntonI ★★★★★
()
Ответ на: комментарий от AntonI

Каждый дубль это всего лишь минус одна строка (актуальным остается последнее значение)? А у ТС теряется 30%

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

CrX ★★★★★
()