В последнее время я реорганизовал некоторые сценарии bash в Python 3.7 как в качестве учебного упражнения, так и для реального использования в проекте. Полученная реализация использует очень большой упорядоченный словарь, скажем, от 2 до 3 миллионов записей. Хранение данных таким способом имеет ряд существенных преимуществ, снижая сложность кода и время обработки. Однако есть одна задача, которая ускользает от меня: как пройти по словарю из известной начальной точки .
Если бы я делал это в C, я бы сделал указатель на желаемую начальную точку и прошел бы по указателю. Если в Python есть аналогичная операция, я не знаю ее и не могу ее найти. Кажется, что все методы, которые я нашел, дублируют некоторую / всю информацию в новый список, что отнимает много времени и тратит много памяти в моем приложении. Также кажется, что вы не можете нарезать словарь, даже если они теперь упорядочены по умолчанию.
Рассмотрим этот придуманный пример словаря латинского алфавита, чьи записи со странным ключом сгруппированы по гласным и согласным, а записи в каждой группе отсортированы в алфавитном порядке:
dd = { # key: ( phonetic, letter, ascii, ebcedic, baudot, morse, hollerith, strokes, kind )
4296433290: ( 'Alfa', 'A', 65, 193, 3, '.-', (12,1), 3, 'vowl' ),
5046716526: ( 'Echo', 'E', 69, 197, 1, '.', (12,5), 4, 'vowl' ),
5000200584: ( 'India', 'I', 73, 201, 6, '..', (12,9), 3, 'vowl' ),
5000971262: ( 'Oscar', 'O', 79, 214, 24, '---', (11,6), 1, 'vowl' ),
5000921625: ( 'Uniform', 'U', 85, 228, 7, '..-', (0,4), 1, 'vowl' ),
4297147083: ( 'Yankee', 'Y', 89, 232, 21, '-.--', (0,8), 3, 'vowl' ),
4297256046: ( 'Bravo', 'B', 66, 194, 25, '-...', (12,2), 3, 'cons' ),
4298140290: ( 'Charlie', 'C', 67, 195, 14, '-.-.', (12,3), 1, 'cons' ),
5036185622: ( 'Delta', 'D', 68, 196, 9, '-..', (12,4), 2, 'cons' ),
5036854221: ( 'Foxtrot', 'F', 70, 198, 13, '..-.', (12,6), 3, 'cons' ),
5037458768: ( 'Golf', 'G', 71, 199, 26, '--.', (12,7), 2, 'cons' ),
5035556903: ( 'Hotel', 'H', 72, 200, 20, '....', (12,8), 3, 'cons' ),
5037119814: ( 'Juliett', 'J', 74, 209, 11, '.---', (11,1), 2, 'cons' ),
5035556831: ( 'Kilo', 'K', 75, 210, 15, '-.-', (11,2), 3, 'cons' ),
4296755665: ( 'Lima', 'L', 76, 211, 18, '.-..', (11,3), 2, 'cons' ),
5035557110: ( 'Mike', 'M', 77, 212, 28, '--', (11,4), 4, 'cons' ),
5037118125: ( 'November', 'N', 78, 213, 12, '-.', (11,5), 3, 'cons' ),
5000423356: ( 'Papa', 'P', 80, 215, 22, '.--.', (11,7), 2, 'cons' ),
5000923300: ( 'Quebec', 'Q', 81, 216, 23, '--.-', (11,8), 2, 'cons' ),
5000969482: ( 'Romeo', 'R', 82, 217, 10, '.-.', (11,9), 3, 'cons' ),
5035943840: ( 'Sierra', 'S', 83, 226, 5, '...', (0,2), 1, 'cons' ),
5045251209: ( 'Tango', 'T', 84, 227, 16, '-', (0,3), 2, 'cons' ),
5000168680: ( 'Victor', 'V', 86, 229, 30, '...-', (0,5), 2, 'cons' ),
4296684445: ( 'Whiskey', 'W', 87, 230, 19, '.--', (0,6), 4, 'cons' ),
5000923277: ( 'Xray', 'X', 88, 231, 29, '-..-', (0,7), 2, 'cons' ),
4296215569: ( 'Zulu', 'Z', 90, 233, 17, '--..', (0,9), 3, 'cons' ),
}
И скажем, я хочу выполнить некоторую обработку согласных. А так как обработка занимает много времени (думаю, дней), я хотел бы сделать это по частям. В этом случае, скажем, 4 согласных одновременно. Я заранее знаю ключи для начала группы, например:
vowlbeg = 4296433290 # key of first vowel
consbeg = 4297256046 # key of first consonant
Но я не могу понять, как воспользоваться этим предузнанием. Например, чтобы обработать 8-11-ю согласную, лучшее, что я могу сделать, это:
beg = 8 # begin processing with 8th consonant
end = 12 # end processing with 11th consonant
kind = 'cons' # desired group
i=-1
for d in dd.items():
if d[1][-1] is not kind: continue
i += 1
if i < beg: continue
if i >= end: break
print('processing:', i, d)
Что дает желаемые результаты, хотя и немного медленно, потому что я хожу по всему словарю с самого начала, пока не найду нужные записи.
processing: 8 (5035556831, ('Kilo', 'K', 75, 210, 15, '-.-', (11, 2), 3, 'cons'))
processing: 9 (4296755665, ('Lima', 'L', 76, 211, 18, '.-..', (11, 3), 2, 'cons'))
processing: 10 (5035557110, ('Mike', 'M', 77, 212, 28, '--', (11, 4), 4, 'cons'))
processing: 11 (5037118125, ('November', 'N', 78, 213, 12, '-.', (11, 5), 3, 'cons'))
Я думаю, что я могу выразить этот цикл более компактно, используя списки или, возможно, словарь, но кажется, что это создаст огромный дубликат в памяти. Возможно, описанный выше метод тоже делает это, я не уверен на 100%.
Что я знаю о моем заказном словаре
- группы, например, гласные и согласные, действительно сгруппированы и не разбросаны.
- внутри каждой группы, записи сортируются в известном желаемом порядке,
- начальный ключ каждой группы
В: Есть ли лучший способ сделать это? Мой план резервного копирования - просто укусить пулю и сохранить дубликат набора кортежей, по одному на группу, чтобы иметь возможность разрезать его. Но это, по сути, удвоит мою память, насколько я понимаю.
Примечание: из этого глупого примера это не очевидно, но возможность доступа к записям по ключам в одном словаре - ОГРОМНОЕ преимущество в моем приложении.