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)

В принципе, получить желаемое удалось, однако при попытке вывести список всех значений из словаря с вариантами, выводятся далеко не все (из 479 выводятся всего 331).

Нужен сам файл, а ещё лучше — пример строк, которые «выводятся» и которые «не выводятся».

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

Файл base.lst. Насчет того, что не выводится - в этом файле например есть варианты раскладок для Беларуси (by: Belarusian (legacy)), но по каким-то причинам она не выводится моим кодом.

Sunderland93 ★★★★★
() автор топика
Ответ на: комментарий от 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 ★★★★
()

Неонка предлагает такой код:

import re

# Открываем файл и считываем его содержимое
with open('file.txt', 'r') as f:
    content = f.read()

# Создаем списки для каждой категории
model = []
layout = []
variant = []
option = []

# Разбиваем содержимое файла на строки и обрабатываем каждую строку
for line in content.split('\n'):
    # Игнорируем пустые строки
    if not line:
        continue

    # Используем регулярные выражения, чтобы определить категорию строки
    match = re.match(r'^!\s*(\w+)\s*$', line)
    if match:
        category = match.group(1)
    else:
        match = re.match(r'^\s*(\w+:\w+|\w+-\w+|\w+)\s*(.*)$', line)
        if not match:
            continue
        key = match.group(1)
        value = match.group(2)
        if category == 'model':
            model.append((key, value))
        elif category == 'layout':
            layout.append((key, value))
        elif category == 'variant':
            variant.append((key, value))
        elif category == 'option':
            option.append((key, value))

# Выводим результаты
print('model:', model)
print('layout:', layout)
print('variant:', variant)
print('option:', option)

На входные:

! model
  pc101           Generic 101-key PC
  pc102           Generic 102-key PC (intl.)
  pc104           Generic 104-key PC
  pc105           Generic 105-key PC (intl.)

! layout
  us              English (US)
  af              Afghani
  ara             Arabic
  al              Albanian

! variant
  chr             us: Cherokee
  euro            us: English (US, euro on 5)
  intl            us: English (US, intl., with dead keys)
  alt-intl        us: English (US, alt. intl.)
  colemak         us: English (Colemak)

! option
  grp                  Switching to another layout
  grp:switch           Right Alt (while pressed)
  grp:lswitch          Left Alt (while pressed)
  grp:lwin_switch      Left Win (while pressed)
  grp:rwin_switch      Left Win (while pressed)
  grp:win_switch       Any Win (while pressed)

получается:

model: [('pc101', 'Generic 101-key PC'), ('pc102', 'Generic 102-key PC (intl.)'), ('pc104', 'Generic 104-key PC'), ('pc105', 'Generic 105-key PC (intl.)')]
layout: [('us', 'English (US)'), ('af', 'Afghani'), ('ara', 'Arabic'), ('al', 'Albanian')]
variant: [('chr', 'us: Cherokee'), ('euro', 'us: English (US, euro on 5)'), ('intl', 'us: English (US, intl., with dead keys)'), ('alt-intl', 'us: English (US, alt. intl.)'), ('colemak', 'us: English (Colemak)')]
option: [('grp', 'Switching to another layout'), ('grp:switch', 'Right Alt (while pressed)'), ('grp:lswitch', 'Left Alt (while pressed)'), ('grp:lwin_switch', 'Left Win (while pressed)'), ('grp:rwin_switch', 'Left Win (while pressed)'), ('grp:win_switch', 'Any Win (while pressed)')]

Регулярку, правда, я правил сам.

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

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

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

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

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

vvn_black ★★★★★
()
Последнее исправление: vvn_black (всего исправлений: 1)

От так ещё можно

use strict;
use warnings;
use Data::Dumper;


my $path = '/usr/share/X11/xkb/rules/base.lst';

open (KEYS, $path) or die "Can't open";

my $current;
my %data = ();

while(<KEYS>)
{
    s/^\s*(.*)\s*$/$1/g;

    my ($b,$e) = split /\s+/,$_, 2;
    next unless $b;

    if($b eq '!')
    {
	$current = $e;
    }
    else
    {
	push @{$data{$current}}, [$b,$e]; 
    }

}

print Dumper(\%data);
solom
()