Может ли цикл ссылаться на список, не называя его в глобальном фрейме? - PullRequest
0 голосов
/ 12 февраля 2019

Мне было поручено сгруппировать список по частоте.Это очень распространенный вопрос о 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, чтобы визуализировать его, и код, кажется, просто знает, что в списке «items» есть четыре «4», два «6» и два «2».Единственное решение, о котором я могу подумать, это то, что python может ссылаться на список в глобальном фрейме без его имени.Или, возможно, возможность использовать значение из словаря "freq".Это правильно?

ссылка на поток: Сортировка списка по частоте в python

1 Ответ

0 голосов
/ 12 февраля 2019

Да, значения 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.


Edit 2019-02-13: Дополнительная информация и пример для Python Tutor

Похоже, что 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)
...