循环可以在全局框架内引用列表而不命名它吗?

Can a loop reference a list without naming it, within a global frame?

我的任务是按频率对列表进行分组。这是 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”在'items'列表。我能想到的唯一解决方案是 python 可以在不命名的情况下引用全局框架中的列表。或者也许能够利用 "freq" 字典中的值。这是正确的吗?

引用线程: Sort list by frequency in python

是的,freq 的值是使第二个循环工作的值。

freq 是一个 Counter:

It is an unordered collection where elements are stored as dictionary keys and their counts are stored as dictionary values.

换句话说,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]) 在第二个循环中迭代时,它所做的只是迭代 numitems 中出现的次数。


编辑 2019-02-13:Python 导师的附加信息和示例

看起来 Python Tutor 按原样表示简单的内置类型(整数、字符串...),而不是 "objects" 在它们自己的单元格中。

如果您使用新对象而不是整数,您可以清楚地看到引用。例如,如果您要包装整数,例如:

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)