От чего зависит порядок элементов при преобразовании набора в список? - PullRequest
0 голосов
/ 29 апреля 2020

Я знаю, что есть несколько похожих вопросов, но я еще не нашел один, в котором говорилось бы о том, что я хотел бы знать. Если это дубликат, укажите это.

Итак, я знаю, что set в Python является неупорядоченной коллекцией, а list можно отсортировать. Что меня интересует, так это то, что определяет порядок упорядочения элементов списка, когда список был преобразован из набора.

Даже если набор «технически» не отсортирован (что, я думаю, означает, что вы не можете взаимодействовать с ним, как если бы вы работали с типами последовательностей), все равно существует порядок в том смысле, что при печати набора например, должен быть элемент, который напечатан первым, вторым, третьим и так далее. Этот вид логики c должен существовать. Но это идет даже дальше, чем это. Например, если вы объявляете два набора в «зашифрованном» состоянии, которые содержат элементы, которые могут быть отсортированы, их представления не только сортируются при их выполнении, union из двух наборов «scrabled» возвращает «отсортированный» также установить:

a = {2, 3, 1}
a
# >>> {1, 2, 3}
b = {7, 4, 5}
b
# >>> {4, 5, 7}

a|b  
# >>> {1, 2, 3, 4, 5, 7} 
b|a
# >>> {1, 2, 3, 4, 5, 7}

Также, когда вы add новый элемент набора и печатаете набор, новый элемент появляется в правильном месте, то есть в том месте, где он должен быть, если набор был отсортировано:

b.add(6)
b
# >>> {4, 5, 6, 7}

Это подводит меня к моему вопросу. Если вы преобразуете наборы в списки, что-то должно определить, в какой позиции каждый элемент набора помещен в новый список. Но, по-видимому, НЕ тот же лог c определяет, в каком порядке печатаются элементы при выполнении набора, о чем я наивно думал. Хотя list(a), list(b) и даже list(a|b) все возвращаемые списки, отсортированные по способу представления наборов, для следующего набора (и, между прочим, всех его перестановок), это по какой-то причине не так:

list(a), list(b), list(a|b)
# >>> ([1, 2, 3], [4, 5, 6, 7], [1, 2, 3, 4, 5, 6, 7])
c = {3, 4, 9}  # or {3, 9, 4}, {4, 3, 9} and so on...
c
# >>> {3, 4, 9}
list(c)  
# >>> [9, 3, 4]

Почему это? Почему логика c, определяющая, каким образом представление набора упорядочено, отличается от той, которая определяет, куда направляется каждый элемент набора при преобразовании набора в список?

Я пытался еще несколько наборов с разными значениями, и мне кажется совершенно случайным, когда порядок представления набора и порядок списка набора совпадают:

# for this set of numbers, the logic is different
d = {3, 4, 11}
d
# >>> {3, 4, 11}
list(d)  
# >>> [11, 3, 4]

# in this case, permutations also result in different sorting of the list
d = {11, 4, 3}
d
# >>> {3, 4, 11}
list(d)  
# >>> [3, 11, 4]

# for this set, the logic appears to be the same again
e = {3, 4, 13}  # or any of its permutations
e
# >>> {3, 4, 13}
list(e)
# >>> [3, 4, 13]

Логика c, который определяет порядок списка и вызова print(set), кажется, одинаковы:

list(d)  
# >>> [3, 11, 4]
print(d)
# >>> {3, 11, 4}

Так что я думаю, как только вы сделаете что-то с набором, другой Логика сортировки c применяется. Если, конечно, вы не создадите объединение:

print(c, d, c|d, list(c|d))
# >>> {9, 3, 4} {3, 11, 4} {3, 4, 9, 11} [3, 4, 9, 11]
f = {3, 4, 9, 11}
f
# >>> {3, 4, 9, 11}
list(f)
# >>> [11, 9, 3, 4]

Если вас интересует вариант использования: как я уже говорил, я наивно думал, что сортировка останется прежней при преобразовании набора в список, когда на самом деле это не так. Неправильная сортировка вызвала ошибку при запуске моего кода. К счастью, это легко исправить, используя sorted(set) вместо list(set), но сначала понадобилось время, чтобы выяснить ошибку.

Итак, с помощью этого вопроса я пытаюсь понять, что происходит, а не искать решение.

1 Ответ

1 голос
/ 29 апреля 2020

Я на Python 3.7.4. и весь мой list(set) ордер совпадает с repr(set) ордером. Вот быстрый тест (код) на 10000 выборок:

import random
import pandas as pd

# create a function to generate random set of 0-999 with len of 3 - 20
f = lambda: set(random.randrange(1000) for i in range(random.randrange(3, 21)))

# create a DataFrame of 10000 rows with random sets
df = pd.DataFrame({'sets': [f() for i in range(10000)]})

# Create a column of repr(set) and retrieve the order in str
df['reprs'] = df['sets'].apply(repr).str.strip('{}')

# Create a column of list(set) and retrieve the order in str
df['lists'] = df['sets'].apply(list).astype(str).str.strip('[]')

# Create a comparison column
df['match'] = df['reprs'].eq(df['lists'])

# Take a look of the reprs and lists...
print(df[['reprs', 'lists']])

# Summarize
summary = df.groupby('match')['sets'].count()
print(summary)

Результаты:

match
True    10000
Name: sets, dtype: int64

Так что я бы вообразил, если что-нибудь Вы хотите обратить внимание на то, как представляется set, что является подробностью реализации согласно первоначальному комментарию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...