Given a list and a number, create a new list that contains each number of list at most N times, without reordering. For example if the input number is 2, and the input list is [1,2,3,1,2,1,2,3], you take [1,2,3,1,2], drop the next [1,2] since this would lead to 1 and 2 being in the result 3 times, and then take 3, which leads to [1,2,3,1,2,3]. With list [20,37,20,21] and number 1, the result would be [20,37,21]
For example i had this like my attempt
from collections import Counter
def delete_nth(order, max_e):
c = Counter(order)
result = []
for key, value in c.items():
if value > max_e:
value = value - 1
return [x for x in c.items()]
and output is
dict_items([(20, 2), (37, 1), (21, 1)])
dict_items([(20, 2), (37, 1), (21, 1)])
From list [20, 37, 20, 21], 1 you get: [(20, 2), (37, 1), (21, 1)] should equal [20, 37, 21]
Log
dict_items([(1, 2), (3, 2), (7, 1), (2, 4)])
dict_items([(1, 2), (3, 2), (7, 1), (2, 4)])
From list [1, 1, 3, 3, 7, 2, 2, 2, 2], 3 you get: [(1, 2), (3, 2), (7, 1), (2, 4)] should equal [1, 1, 3, 3, 7, 2, 2, 2]
Log
dict_items([(1, 5), (2, 4), (3, 4), (4, 1), (5, 1)])
dict_items([(1, 5), (2, 4), (3, 4), (4, 1), (5, 1)])
dict_items([(1, 5), (2, 4), (3, 4), (4, 1), (5, 1)])
dict_items([(1, 5), (2, 4), (3, 4), (4, 1), (5, 1)])
dict_items([(1, 5), (2, 4), (3, 4), (4, 1), (5, 1)])
dict_items([(1, 5), (2, 4), (3, 4), (4, 1), (5, 1)])
From list [1, 2, 3, 1, 1, 2, 1, 2, 3, 3, 2, 4, 5, 3, 1], 3 you get: [(1, 5), (2, 4), (3, 4), (4, 1), (5, 1)] should equal [1, 2, 3, 1, 1, 2, 2, 3, 3, 4, 5]
From list [1, 1, 1, 1, 1], 5 you get: [(1, 5)] should equal [1, 1, 1, 1, 1]
Test Passed
Random tests
Testing for delete_nth([21, 45, 29, 29, 29, 6, 24, 45, 45, 45, 29, 21, 29, 24, 6, 45, 21, 38, 45, 21, 24, 45, 24, 6, 6, 29, 45, 29, 6, 45, 21, 29], 4)
Log
dict_items([(21, 5), (45, 9), (29, 8), (6, 5), (24, 4), (38, 1)])
dict_items([(21, 5), (45, 9), (29, 8), (6, 5), (24, 4), (38, 1)])
dict_items([(21, 5), (45, 9), (29, 8), (6, 5), (24, 4), (38, 1)])
dict_items([(21, 5), (45, 9), (29, 8), (6, 5), (24, 4), (38, 1)])
dict_items([(21, 5), (45, 9), (29, 8), (6, 5), (24, 4), (38, 1)])
dict_items([(21, 5), (45, 9), (29, 8), (6, 5), (24, 4), (38, 1)])
dict_items([(21, 5), (45, 9), (29, 8), (6, 5), (24, 4), (38, 1)])
dict_items([(21, 5), (45, 9), (29, 8), (6, 5), (24, 4), (38, 1)])
It should work on random inputs too!: [(21, 5), (45, 9), (29, 8), (6, 5), (24, 4), (38, 1)] should equal [21, 45, 29, 29, 29, 6, 24, 45, 45, 45, 29, 21, 24, 6, 21, 38, 21, 24, 24, 6, 6]
Testing for delete_nth([18, 18, 18, 18, 6, 23, 18, 46, 18, 31, 18, 31, 23, 18, 18, 31], 7)
Log
dict_items([(18, 9), (6, 1), (23, 2), (46, 1), (31, 3)])
dict_items([(18, 9), (6, 1), (23, 2), (46, 1), (31, 3)])
It should work on random inputs too!: [(18, 9), (6, 1), (23, 2), (46, 1), (31, 3)] should equal [18, 18, 18, 18, 6, 23, 18, 46, 18, 31, 18, 31, 23, 31]
CodePudding user response:
Doing value = value - 1
only decrements the local variable value
inside the loop; it doesn't decrement the actual value inside the Counter.
I might try building the list inside the loop as you decrement the counter:
from collections import Counter
def delete_nth(order, max_e):
# Build counter with maximum count max_e.
counts = {
i: min(max_e, count)
for i, count in Counter(order).items()
}
# Build result by iterating over original list.
result = []
for i in order:
if not counts[i]:
continue
counts[i] -= 1
result.append(i)
return result
assert delete_nth([1,2,3,1,2,1,2,3], 2) == [1,2,3,1,2,3]
CodePudding user response:
Perhaps something like this?
def keep_at_most_n(arr, n):
count = {}
output = []
for element in arr:
if count.get(element, 0) < n:
output.append(element)
count[element] = count.get(element, 0) 1
return output