Python: Как реализовать алгоритм создания списков в словаре
Из времени входа и выхода (попарно):
intervals = [
{
'lesson': [1594663200, 1594666800],
'pupil': [1594663340, 1594663389, 1594663390, 1594663395, 1594663396, 1594666472],
'tutor': [1594663290, 1594663430, 1594663443, 1594666473]
}
]
Нужно чтобы создавался списки в словарях: 0,1 : 0,1 ; 0,1 : 2,3 ; 2,3 : 0,1 ; 2,3 : 2,3...
{
'lesson': [1594663200, 1594666800],
'pupil': [1594663340, 1594663389],
'tutor': [1594663290, 1594663430]
}
{
'lesson': [1594663200, 1594666800],
'pupil': [1594663340, 1594663389],
'tutor': [1594663443, 1594666473]
}
{
'lesson': [1594663200, 1594666800],
'pupil': [1594663390, 1594663395],
'tutor': [1594663290, 1594663430]
}
{
'lesson': [1594663200, 1594666800],
'pupil': [1594663390, 1594663395],
'tutor': [1594663443, 1594666473]
}
...
Ответы (2 шт):
Тогда все очень просто: делаем два цикла, где внешний идет по парам 'pupil', а внутренний - по парам 'tutor':
ans = []
for i in range(0, len(intervals['pupil']), 2):
for j in range(0, len(intervals['tutor']), 2):
ans.append({'lesson': intervals['lesson'], \
'pupil': intervals['pupil'][i:i+2], \
'tutor': intervals['turor'][j:j+2] })
Длинный, но красивый и универсальный ответ. Работает для любого количества списков, не задействует ни одного цикла, может служить иллюстрацией для генераторов и модуля itertools.
План такой: разрезать все списки на пары, к спискам пар применить декартово произведение, его элементы преобразовать в словари.
Данные для работы:
task = {
'lesson': [1594663200, 1594666800],
'pupil': [1594663340, 1594663389, 1594663390, 1594663395, 1594663396, 1594666472],
'tutor': [1594663290, 1594663430, 1594663443, 1594666473]
}
Режем список на пары. Это настоящая магия:
def pairs(iterable):
return zip(*[iter(iterable)] * 2)
@>>> print(*pairs(task['pupil']), sep='\n') (1594663340, 1594663389) (1594663390, 1594663395) (1594663396, 1594666472)
Режем все значения в словаре на помеченные пары:
def tagged_pairs(task):
for k, v in task.items():
yield tuple((k, p) for p in pairs(v))
@>>> print(*tagged_pairs(task), sep='\n') (('lesson', (1594663200, 1594666800)),) (('pupil', (1594663340, 1594663389)), ('pupil', (1594663390, 1594663395)), ('pupil', (1594663396, 1594666472))) (('tutor', (1594663290, 1594663430)), ('tutor', (1594663443, 1594666473)))
Декартово произведение помеченных пар (itertools.product):
@>>> print(*itertools.product(*tagged_pairs(task)), sep='\n') (('lesson', (1594663200, 1594666800)), ('pupil', (1594663340, 1594663389)), ('tutor', (1594663290, 1594663430))) (('lesson', (1594663200, 1594666800)), ('pupil', (1594663340, 1594663389)), ('tutor', (1594663443, 1594666473))) (('lesson', (1594663200, 1594666800)), ('pupil', (1594663390, 1594663395)), ('tutor', (1594663290, 1594663430))) (('lesson', (1594663200, 1594666800)), ('pupil', (1594663390, 1594663395)), ('tutor', (1594663443, 1594666473))) (('lesson', (1594663200, 1594666800)), ('pupil', (1594663396, 1594666472)), ('tutor', (1594663290, 1594663430))) (('lesson', (1594663200, 1594666800)), ('pupil', (1594663396, 1594666472)), ('tutor', (1594663443, 1594666473)))
Элементы декартова произведения превращаем в словари:
def groups(task):
return map(dict, itertools.product(*tagged_pairs(task)))
@>>> print(*groups(task), sep='\n') {'lesson': (1594663200, 1594666800), 'pupil': (1594663340, 1594663389), 'tutor': (1594663290, 1594663430)} {'lesson': (1594663200, 1594666800), 'pupil': (1594663340, 1594663389), 'tutor': (1594663443, 1594666473)} {'lesson': (1594663200, 1594666800), 'pupil': (1594663390, 1594663395), 'tutor': (1594663290, 1594663430)} {'lesson': (1594663200, 1594666800), 'pupil': (1594663390, 1594663395), 'tutor': (1594663443, 1594666473)} {'lesson': (1594663200, 1594666800), 'pupil': (1594663396, 1594666472), 'tutor': (1594663290, 1594663430)} {'lesson': (1594663200, 1594666800), 'pupil': (1594663396, 1594666472), 'tutor': (1594663443, 1594666473)}