Распределить значения по набору кортежей в Python - PullRequest
1 голос
/ 29 апреля 2020

Я пытаюсь создать ротацию для парных разговоров из-за блокировки.

У меня есть список коллег.

И я создал список дней.

Я хочу назначить дни для каждой пары последовательно, пока все пары не будут назначены.

Но я не могу понять, как отследить, была ли пара уже назначена и как "запустить" до конца коллег ".

Вот что у меня есть:

import itertools
import datetime as dt
import numpy as np

colleagues = ["C",
              "S",
              "D",
              "I",
              "P"]

colleague_pairs = sorted(list(itertools.combinations(colleagues, 2)))
start_date = dt.datetime.today() + dt.timedelta(days=5)
dates = [start_date]
current_date = dates[-1]
while len(dates) < (len(colleagues) -1):
    new_date = current_date + dt.timedelta(days=1)
    if new_date.weekday() < 5:
        dates.append(new_date)
    current_date = new_date
working_days = [date.strftime('%Y-%m-%d') for date in dates ] 


[('C', 'D'), ('C', 'I'), ('C', 'P'), ('C', 'S'), 
 ('D', 'I'), ('D', 'P'), 
 ('I', 'P'), 
 ('S', 'D'), ('S', 'I'), ('S', 'P')]
['2020-05-04', '2020-05-05', '2020-05-06', '2020-05-07']

Я хочу в итоге все даты применить ко всем уникальным парам:

{('C', 'D'): '2020-05-04'}
{('C', 'I'): '2020-05-05'}
{('C', 'P'): '2020-05-06'}
{('C', 'S'): '2020-05-07'}

{('S', 'D'): '2020-05-05'}
{('S', 'I'): '2020-05-06'}
{('S', 'P'): '2020-05-07'}

{('D', 'I'): '2020-05-06'}
{('D', 'P'): '2020-05-07'}

{('I', 'P'): '2020-05-07'}

Я пытался перебирать все дни, но, очевидно, это не сработало:

for pair in colleague_pairs:
    for day in working_days:
        print({pair:day})

{('C', 'D'): '2020-05-04'}
{('C', 'D'): '2020-05-05'}
{('C', 'D'): '2020-05-06'}
{('C', 'D'): '2020-05-07'}
{('C', 'I'): '2020-05-04'}
{('C', 'I'): '2020-05-05'}
{('C', 'I'): '2020-05-06'}
{('C', 'I'): '2020-05-07'}
{('C', 'P'): '2020-05-04'}
{('C', 'P'): '2020-05-05'}
{('C', 'P'): '2020-05-06'}
{('C', 'P'): '2020-05-07'}
{('C', 'S'): '2020-05-04'}
{('C', 'S'): '2020-05-05'}
{('C', 'S'): '2020-05-06'}
{('C', 'S'): '2020-05-07'}
{('D', 'I'): '2020-05-04'}
{('D', 'I'): '2020-05-05'}
{('D', 'I'): '2020-05-06'}
{('D', 'I'): '2020-05-07'}
{('D', 'P'): '2020-05-04'}
{('D', 'P'): '2020-05-05'}
{('D', 'P'): '2020-05-06'}
{('D', 'P'): '2020-05-07'}
{('I', 'P'): '2020-05-04'}
{('I', 'P'): '2020-05-05'}
{('I', 'P'): '2020-05-06'}
{('I', 'P'): '2020-05-07'}
{('S', 'D'): '2020-05-04'}
{('S', 'D'): '2020-05-05'}
{('S', 'D'): '2020-05-06'}
{('S', 'D'): '2020-05-07'}
{('S', 'I'): '2020-05-04'}
{('S', 'I'): '2020-05-05'}
{('S', 'I'): '2020-05-06'}
{('S', 'I'): '2020-05-07'}
{('S', 'P'): '2020-05-04'}
{('S', 'P'): '2020-05-05'}
{('S', 'P'): '2020-05-06'}
{('S', 'P'): '2020-05-07'} 

Я чувствую, что должно быть слово для комбинаций, которые я хочу, но я не могу понять это.

Как мне настроить то, что у меня есть, на то, что мне нужно?

Ответы [ 2 ]

1 голос
/ 29 апреля 2020

Так как вы хотите сгруппировать по первой букве и назначить дни с начала, вам нужно будет создать новый двумерный массив следующим образом:

colleague_pairs = [
    [('C', 'D'), ('C', 'I'), ('C', 'P'), ('C', 'S')],
    [('S', 'D'), ('S', 'I'), ('S', 'P')],
    [('D', 'I'), ('D', 'P')],
    [('I', 'P')]
]

Для достижения этого формата вы можете использовать словари, например, так:


colleague_pairs = [('C', 'D'), ('C', 'I'), ('C', 'P'), ('C', 'S'), ('S', 'D'), ('S', 'I'), ('S', 'P'), ('D', 'I'), ('D', 'P'), ('I', 'P')]
colleague_pairs_dict = {}
for cp in colleague_pairs:
    key = cp[0]
    if key not in colleague_pairs_dict.keys():
        colleague_pairs_dict[key] = []
        colleague_pairs_dict[key].append(i)
    else:
        colleague_pairs_dict[key].append(i)

two_dim_colleague_pairs = colleague_pairs_dict.values()

Затем вы можете использовать следующий код для получения желаемого результата.

working_days = ['2020-05-04', '2020-05-05', '2020-05-06', '2020-05-07']
desired_output = []
days_index = 0

for i in range(len(colleague_pairs)):
    for j in range(len(colleague_pairs[i])):
        desired_output.append( { colleague_pairs[i][j] : working_days[days_index] } )
        days_index += 1
        if(days_index == len(working_days)):
            days_index = abs(len(working_days) - len(colleague_pairs[i])) + 1
    days_index = abs(len(working_days) - len(colleague_pairs[i])) + 1
1 голос
/ 29 апреля 2020

С точки зрения получения вашего точного предложенного результата, это мое текущее предложение:

cp = colleague_pairs[:]
#cpKeys == colleague_pairs is unique pairs. All start with a key, basically.
cpKeys = {i[0] for i in colleague_pairs}
#Assign those keys to a date. That date is the day you start using that key.
#startDay = {k:working_days.index(v) for k,v in zip(cpKeys,working_days)}#x is arbitrary. Doesn't mean anything, here, as a name.
startDay = {'C':0,'D':2,'S':1,'I':3}
print(startDay)
#Make a dict of colleague_pair: 
final = {i:'' for i in sorted(colleague_pairs)}

for i in [('C', 'D'),
        ('C', 'I'),
        ('C', 'P'),
        ('C', 'S'),
        ('S', 'D'),
        ('S', 'I'),
        ('S', 'P'),  
        ('D', 'I'),
        ('D', 'P'),
        ('I', 'P'),]:
    #for each cp
    #declare the key
    key = i[0]
    #Get the date to use by connecting the key
    #to the startDay index position for working_days
    dateToUse = working_days[ startDay[key] ]
    final[i] = dateToUse
    startDay[key] += 1
    if startDay[key] >= len(working_days):
        startDay[key] = 0

Я сделал это таким образом, чтобы получить точный результат, который вы предложили, в порядке, который вы предложили. Суть идеи заключается в том, чтобы использовать первый символ кортежа в качестве ключа и отслеживать дни, с которых начинается каждый из них. Если colleague_pairs - это уникальные пары, это должно сработать, если каждый начальный день - это другой день.

...