我受命按频率对列表进行分组。这是关于SOF的一个非常普遍的问题,到目前为止,该论坛的教育程度很高。但是,在给出的所有示例中,只有以下一个示例可以实现:
使用这两个列表:
[4, 6, 2, 2, 6, 4, 4, 4]
[17, 99, 42]
以下作为解决该问题的通用代码失败。
from collections import Counter
freq = Counter(items)
# Ex 1
# The items dont stay grouped in the final list :(
sorted(items, key = items.count, reverse=True)
sorted(items, key=lambda x: -freq[x])
[4, 4, 4, 4, 6, 2, 2, 6]
# Ex 2
# The order that the items appear in the list gets rearranged :(
sorted(sorted(items), key=freq.get, reverse=True)
[4, 4, 4, 4, 2, 2, 6, 6]
# Ex 3
# With a list of integers, after the quantity gets sorted,
# the int value gets sorted :(
sorted(items, key=lambda x: (freq[x], x), reverse=True)
[99, 42, 17]
我确实找到了一个行之有效的解决方案:
s_list = sorted(freq, key=freq.get, reverse=True)
new_list = []
for num in s_list:
for rep in range(freq[num]):
new_list.append(num)
print(new_list)
我无法弄清楚第二个循环如何引用出现次数。
我通过pythontutor运行了该过程以对其进行可视化,并且代码似乎只知道在“项目”列表中有四个“ 4”,两个“ 6”和两个“ 2”。我能想到的唯一解决方案是python可以在全局框架中引用列表而无需命名。或者也许能够利用“频率”字典中的值。这是正确的吗?
答案 0 :(得分:1)
是的,freq
的值使第二个循环起作用。
freq
是Counter
:
这是一个无序集合,其中元素存储为字典键,其计数存储为字典值。
换句话说,freq
是一个字典,其中的键是items
的唯一元素,映射到它们在items
中出现的次数。
并举例说明:
>>> from collections import Counter
>>> items = [4, 6, 2, 2, 6, 4, 4, 4]
>>> freq = Counter(items)
>>> freq
Counter({4: 4, 6: 2, 2: 2})
因此,在第二个循环中迭代range(freq[num])
时,它所做的就是迭代num
在items
中出现的次数。
编辑2019-02-13: Python导师的其他信息和示例
Python Tutor看起来像按原样表示简单的内置类型(整数,字符串等),而不是在其自己的单元格中表示为“对象”。
如果使用新对象而不是整数,则可以清楚地看到引用。例如,如果要包装整数,例如:
from collections import Counter
class MyIntWrapper:
def __init__(self, value):
self.value = value
items = [4, 6, 2, 2, 6, 4, 4, 4]
items_wrapped = [MyIntWrapper(item) for item in items]
freq = Counter(items_wrapped)
s_list = sorted(freq, key=freq.get, reverse=True)
new_list = []
for num in s_list:
for rep in range(freq[num]):
new_list.append(num)