Внедрение Python Round Robin поверх dict - PullRequest
0 голосов
/ 24 ноября 2018

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

Для быстрых вставок я использую defaultdict.

{
    "john":   [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
    "ram":    [2, 6],
    "bruce":  [1, 4, 5],
    "willam": [7, 1],
}

Единственная проблема, которой подвержена эта структура данных, это "john", который выдает слишком много запросов, а сервер не можетчестно и своевременно обслуживать других клиентов.

Поэтому я подумал, что Roundrobin может прийти на помощь, дав мне итератор, который выдает таких клиентов -

"john", 0
"ram", 2
"bruce", 1
"willam", 7
"john", 1
"ram", 6
"bruce", 4
... 

Может кто-нибудь сказать, пожалуйста, как я могу реализоватьтакой эффективный итератор?

РЕДАКТИРОВАТЬ: Это то, что я придумал.У кого-нибудь есть лучший способ сделать что-то?

def roundrobin(requests): 
    remaining = set(requests) 

    index = 0 
    while remaining: 
        up_next = set() 
        for key in remaining: 
            try: 
                print(key, requests[key][index])
            except IndexError: 
                continue 
            up_next.add(key) 
        remaining = up_next 
        index += 1 

Он выдает следующий вывод

ram 2
john 0
willam 7
bruce 1
bruce 4
ram 6
john 1
willam 1
john 2
bruce 5
john 3
john 4
john 5
john 6
john 7
john 8
john 9
john 10
john 11
john 12
john 13
john 14
john 15
john 16
john 17
john 18
john 19

Ответы [ 2 ]

0 голосов
/ 25 ноября 2018

Вы можете сделать ведро для каждого запрашивающего, и циклически нажимать itertools.cycle, каждый раз хлопая.

import itertools

all_requests = {
    "john":   [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
    "ram":    [2, 6],
    "bruce":  [1, 4, 5],
    "willam": [7, 1],
}

# handle requests:
for requester in itertools.cycle(all_requests):
    request, all_requests[requester] = all_requests[requester][0], all_requests[requester][1:]
    # Intuitively this seems faster than request = all_requests[requester].pop(0), but I could be wrong
    # you should profile this before using it in production code, or see my note below.

    response = handle_request(request)
    send_response(response)

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

0 голосов
/ 25 ноября 2018

Я не думаю, что это может быть лучше, чем это.

def roundrobin2(requests):
    index = 0
    while requests:
        for key in list(requests):
            try:
                key, requests[key][index]
            except IndexError:
                del requests[key]
            else:
                index += 1
...