Python Implementing Round Robin over a dict
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
I am trying to make a client-server application, where clients register for a request, and get response at a later time.
For fast insertions, I use a 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],
}
The only problem this data structure is susceptible to, is "john"
who's issuing too many requests, and the server cannot serve other clients fairly in time.
So I thought roundrobin may come to rescue, giving me an iterator that yields clients like this -
"john", 0
"ram", 2
"bruce", 1
"willam", 7
"john", 1
"ram", 6
"bruce", 4
...
Can anyone please tell me how I can implement such an iterator in an efficient manner?
EDIT: This is what I came up with. Does anyone have a better way to do things?
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
It produces the following output
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
python round-robin
add a comment |
I am trying to make a client-server application, where clients register for a request, and get response at a later time.
For fast insertions, I use a 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],
}
The only problem this data structure is susceptible to, is "john"
who's issuing too many requests, and the server cannot serve other clients fairly in time.
So I thought roundrobin may come to rescue, giving me an iterator that yields clients like this -
"john", 0
"ram", 2
"bruce", 1
"willam", 7
"john", 1
"ram", 6
"bruce", 4
...
Can anyone please tell me how I can implement such an iterator in an efficient manner?
EDIT: This is what I came up with. Does anyone have a better way to do things?
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
It produces the following output
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
python round-robin
1
You could interleave all the names.itertools
probably has an interleave function.
– Carcigenicate
Nov 24 '18 at 20:59
@Carcigenicate updated answer
– Dev Aggarwal
Nov 24 '18 at 21:13
2
"better" how? Do you have a specific problem with it?
– jonrsharpe
Nov 24 '18 at 21:17
1
I find it difficult to digest making a newset()
on each iteration, and adding keys to it.
– Dev Aggarwal
Nov 24 '18 at 21:20
add a comment |
I am trying to make a client-server application, where clients register for a request, and get response at a later time.
For fast insertions, I use a 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],
}
The only problem this data structure is susceptible to, is "john"
who's issuing too many requests, and the server cannot serve other clients fairly in time.
So I thought roundrobin may come to rescue, giving me an iterator that yields clients like this -
"john", 0
"ram", 2
"bruce", 1
"willam", 7
"john", 1
"ram", 6
"bruce", 4
...
Can anyone please tell me how I can implement such an iterator in an efficient manner?
EDIT: This is what I came up with. Does anyone have a better way to do things?
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
It produces the following output
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
python round-robin
I am trying to make a client-server application, where clients register for a request, and get response at a later time.
For fast insertions, I use a 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],
}
The only problem this data structure is susceptible to, is "john"
who's issuing too many requests, and the server cannot serve other clients fairly in time.
So I thought roundrobin may come to rescue, giving me an iterator that yields clients like this -
"john", 0
"ram", 2
"bruce", 1
"willam", 7
"john", 1
"ram", 6
"bruce", 4
...
Can anyone please tell me how I can implement such an iterator in an efficient manner?
EDIT: This is what I came up with. Does anyone have a better way to do things?
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
It produces the following output
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
python round-robin
python round-robin
edited Nov 24 '18 at 21:12
Dev Aggarwal
asked Nov 24 '18 at 20:57
Dev AggarwalDev Aggarwal
402313
402313
1
You could interleave all the names.itertools
probably has an interleave function.
– Carcigenicate
Nov 24 '18 at 20:59
@Carcigenicate updated answer
– Dev Aggarwal
Nov 24 '18 at 21:13
2
"better" how? Do you have a specific problem with it?
– jonrsharpe
Nov 24 '18 at 21:17
1
I find it difficult to digest making a newset()
on each iteration, and adding keys to it.
– Dev Aggarwal
Nov 24 '18 at 21:20
add a comment |
1
You could interleave all the names.itertools
probably has an interleave function.
– Carcigenicate
Nov 24 '18 at 20:59
@Carcigenicate updated answer
– Dev Aggarwal
Nov 24 '18 at 21:13
2
"better" how? Do you have a specific problem with it?
– jonrsharpe
Nov 24 '18 at 21:17
1
I find it difficult to digest making a newset()
on each iteration, and adding keys to it.
– Dev Aggarwal
Nov 24 '18 at 21:20
1
1
You could interleave all the names.
itertools
probably has an interleave function.– Carcigenicate
Nov 24 '18 at 20:59
You could interleave all the names.
itertools
probably has an interleave function.– Carcigenicate
Nov 24 '18 at 20:59
@Carcigenicate updated answer
– Dev Aggarwal
Nov 24 '18 at 21:13
@Carcigenicate updated answer
– Dev Aggarwal
Nov 24 '18 at 21:13
2
2
"better" how? Do you have a specific problem with it?
– jonrsharpe
Nov 24 '18 at 21:17
"better" how? Do you have a specific problem with it?
– jonrsharpe
Nov 24 '18 at 21:17
1
1
I find it difficult to digest making a new
set()
on each iteration, and adding keys to it.– Dev Aggarwal
Nov 24 '18 at 21:20
I find it difficult to digest making a new
set()
on each iteration, and adding keys to it.– Dev Aggarwal
Nov 24 '18 at 21:20
add a comment |
2 Answers
2
active
oldest
votes
I don't think it can get any better than this.
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
add a comment |
You could make a bucket for each requester, and cycle through with itertools.cycle
, popping each time.
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)
Note that I'm often pulling from the head of this list, so you should maybe use collections.deque
instead which has fast pops and pushes from head or tail.
I just realized that I need to have a functionality to selectively ignore/select a request, based on a processing step. Does that make sense?
– Dev Aggarwal
Nov 24 '18 at 21:57
What I think I need, is the ability to tell the index ofitertools.cycle()
's iteration
– Dev Aggarwal
Nov 24 '18 at 22:02
gist.github.com/devxpy/beea2b967913aabdadc144834d0d4722 Here is what I came up with. ( I was already using a deque anyway, since the clients need to have a personal queue )
– Dev Aggarwal
Nov 24 '18 at 22:08
Maybe a linked list is what I really need :/
– Dev Aggarwal
Nov 24 '18 at 22:13
@DevAggarwal you could use a priority queue (queue.PriorityQueue
that takes items in the form of(priority_number, data)
and gets the item with the lowest priority on eachq.get()
) and a dictionary of requesters with values of their current priority. Each request could raise someone's priority (which has the effect of making their responses come later in the queue) with a callback to lower everyone's priority if there's nothing to get from the queue.
– Adam Smith
Nov 25 '18 at 0:24
|
show 3 more comments
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53462299%2fpython-implementing-round-robin-over-a-dict%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
I don't think it can get any better than this.
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
add a comment |
I don't think it can get any better than this.
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
add a comment |
I don't think it can get any better than this.
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
I don't think it can get any better than this.
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
answered Nov 24 '18 at 21:34
Dev AggarwalDev Aggarwal
402313
402313
add a comment |
add a comment |
You could make a bucket for each requester, and cycle through with itertools.cycle
, popping each time.
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)
Note that I'm often pulling from the head of this list, so you should maybe use collections.deque
instead which has fast pops and pushes from head or tail.
I just realized that I need to have a functionality to selectively ignore/select a request, based on a processing step. Does that make sense?
– Dev Aggarwal
Nov 24 '18 at 21:57
What I think I need, is the ability to tell the index ofitertools.cycle()
's iteration
– Dev Aggarwal
Nov 24 '18 at 22:02
gist.github.com/devxpy/beea2b967913aabdadc144834d0d4722 Here is what I came up with. ( I was already using a deque anyway, since the clients need to have a personal queue )
– Dev Aggarwal
Nov 24 '18 at 22:08
Maybe a linked list is what I really need :/
– Dev Aggarwal
Nov 24 '18 at 22:13
@DevAggarwal you could use a priority queue (queue.PriorityQueue
that takes items in the form of(priority_number, data)
and gets the item with the lowest priority on eachq.get()
) and a dictionary of requesters with values of their current priority. Each request could raise someone's priority (which has the effect of making their responses come later in the queue) with a callback to lower everyone's priority if there's nothing to get from the queue.
– Adam Smith
Nov 25 '18 at 0:24
|
show 3 more comments
You could make a bucket for each requester, and cycle through with itertools.cycle
, popping each time.
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)
Note that I'm often pulling from the head of this list, so you should maybe use collections.deque
instead which has fast pops and pushes from head or tail.
I just realized that I need to have a functionality to selectively ignore/select a request, based on a processing step. Does that make sense?
– Dev Aggarwal
Nov 24 '18 at 21:57
What I think I need, is the ability to tell the index ofitertools.cycle()
's iteration
– Dev Aggarwal
Nov 24 '18 at 22:02
gist.github.com/devxpy/beea2b967913aabdadc144834d0d4722 Here is what I came up with. ( I was already using a deque anyway, since the clients need to have a personal queue )
– Dev Aggarwal
Nov 24 '18 at 22:08
Maybe a linked list is what I really need :/
– Dev Aggarwal
Nov 24 '18 at 22:13
@DevAggarwal you could use a priority queue (queue.PriorityQueue
that takes items in the form of(priority_number, data)
and gets the item with the lowest priority on eachq.get()
) and a dictionary of requesters with values of their current priority. Each request could raise someone's priority (which has the effect of making their responses come later in the queue) with a callback to lower everyone's priority if there's nothing to get from the queue.
– Adam Smith
Nov 25 '18 at 0:24
|
show 3 more comments
You could make a bucket for each requester, and cycle through with itertools.cycle
, popping each time.
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)
Note that I'm often pulling from the head of this list, so you should maybe use collections.deque
instead which has fast pops and pushes from head or tail.
You could make a bucket for each requester, and cycle through with itertools.cycle
, popping each time.
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)
Note that I'm often pulling from the head of this list, so you should maybe use collections.deque
instead which has fast pops and pushes from head or tail.
answered Nov 24 '18 at 21:43
Adam SmithAdam Smith
35.6k73377
35.6k73377
I just realized that I need to have a functionality to selectively ignore/select a request, based on a processing step. Does that make sense?
– Dev Aggarwal
Nov 24 '18 at 21:57
What I think I need, is the ability to tell the index ofitertools.cycle()
's iteration
– Dev Aggarwal
Nov 24 '18 at 22:02
gist.github.com/devxpy/beea2b967913aabdadc144834d0d4722 Here is what I came up with. ( I was already using a deque anyway, since the clients need to have a personal queue )
– Dev Aggarwal
Nov 24 '18 at 22:08
Maybe a linked list is what I really need :/
– Dev Aggarwal
Nov 24 '18 at 22:13
@DevAggarwal you could use a priority queue (queue.PriorityQueue
that takes items in the form of(priority_number, data)
and gets the item with the lowest priority on eachq.get()
) and a dictionary of requesters with values of their current priority. Each request could raise someone's priority (which has the effect of making their responses come later in the queue) with a callback to lower everyone's priority if there's nothing to get from the queue.
– Adam Smith
Nov 25 '18 at 0:24
|
show 3 more comments
I just realized that I need to have a functionality to selectively ignore/select a request, based on a processing step. Does that make sense?
– Dev Aggarwal
Nov 24 '18 at 21:57
What I think I need, is the ability to tell the index ofitertools.cycle()
's iteration
– Dev Aggarwal
Nov 24 '18 at 22:02
gist.github.com/devxpy/beea2b967913aabdadc144834d0d4722 Here is what I came up with. ( I was already using a deque anyway, since the clients need to have a personal queue )
– Dev Aggarwal
Nov 24 '18 at 22:08
Maybe a linked list is what I really need :/
– Dev Aggarwal
Nov 24 '18 at 22:13
@DevAggarwal you could use a priority queue (queue.PriorityQueue
that takes items in the form of(priority_number, data)
and gets the item with the lowest priority on eachq.get()
) and a dictionary of requesters with values of their current priority. Each request could raise someone's priority (which has the effect of making their responses come later in the queue) with a callback to lower everyone's priority if there's nothing to get from the queue.
– Adam Smith
Nov 25 '18 at 0:24
I just realized that I need to have a functionality to selectively ignore/select a request, based on a processing step. Does that make sense?
– Dev Aggarwal
Nov 24 '18 at 21:57
I just realized that I need to have a functionality to selectively ignore/select a request, based on a processing step. Does that make sense?
– Dev Aggarwal
Nov 24 '18 at 21:57
What I think I need, is the ability to tell the index of
itertools.cycle()
's iteration– Dev Aggarwal
Nov 24 '18 at 22:02
What I think I need, is the ability to tell the index of
itertools.cycle()
's iteration– Dev Aggarwal
Nov 24 '18 at 22:02
gist.github.com/devxpy/beea2b967913aabdadc144834d0d4722 Here is what I came up with. ( I was already using a deque anyway, since the clients need to have a personal queue )
– Dev Aggarwal
Nov 24 '18 at 22:08
gist.github.com/devxpy/beea2b967913aabdadc144834d0d4722 Here is what I came up with. ( I was already using a deque anyway, since the clients need to have a personal queue )
– Dev Aggarwal
Nov 24 '18 at 22:08
Maybe a linked list is what I really need :/
– Dev Aggarwal
Nov 24 '18 at 22:13
Maybe a linked list is what I really need :/
– Dev Aggarwal
Nov 24 '18 at 22:13
@DevAggarwal you could use a priority queue (
queue.PriorityQueue
that takes items in the form of (priority_number, data)
and gets the item with the lowest priority on each q.get()
) and a dictionary of requesters with values of their current priority. Each request could raise someone's priority (which has the effect of making their responses come later in the queue) with a callback to lower everyone's priority if there's nothing to get from the queue.– Adam Smith
Nov 25 '18 at 0:24
@DevAggarwal you could use a priority queue (
queue.PriorityQueue
that takes items in the form of (priority_number, data)
and gets the item with the lowest priority on each q.get()
) and a dictionary of requesters with values of their current priority. Each request could raise someone's priority (which has the effect of making their responses come later in the queue) with a callback to lower everyone's priority if there's nothing to get from the queue.– Adam Smith
Nov 25 '18 at 0:24
|
show 3 more comments
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53462299%2fpython-implementing-round-robin-over-a-dict%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
You could interleave all the names.
itertools
probably has an interleave function.– Carcigenicate
Nov 24 '18 at 20:59
@Carcigenicate updated answer
– Dev Aggarwal
Nov 24 '18 at 21:13
2
"better" how? Do you have a specific problem with it?
– jonrsharpe
Nov 24 '18 at 21:17
1
I find it difficult to digest making a new
set()
on each iteration, and adding keys to it.– Dev Aggarwal
Nov 24 '18 at 21:20