保持冻结集中元素的顺序
Maintaining the order of the elements in a frozen set
我有一个元组列表,每个元组包含一个字符串和两个整数。该列表如下所示:
x = [('a',1,2), ('b',3,4), ('x',5,6), ('a',2,1)]
该列表包含数千个这样的元组。现在,如果我想获得独特的组合,我可以按如下方式在列表中执行 frozenset
:
y = set(map(frozenset, x))
这给了我以下结果:
{frozenset({'a', 2, 1}), frozenset({'x', 5, 6}), frozenset({3, 'b', 4})}
我知道 set 是一个 unordered 数据结构,这是正常情况,但我想保留此处元素的顺序,以便之后可以将元素插入到pandas
数据框。数据框将如下所示:
Name Marks1 Marks2
0 a 1 2
1 b 3 4
2 x 5 6
没有订购 frozensets。您可以改为创建排序的元组来检查项目是否存在,如果元组不存在于集合中则添加原始元组:
y = set()
lst = []
for i in x:
t = tuple(sorted(i, key=str)
if t not in y:
y.add(t)
lst.append(i)
print(lst)
# [('a', 1, 2), ('b', 3, 4), ('x', 5, 6)]
保留第一个条目。
与其直接对 frozenset
的 set
进行操作,不如将其用作辅助数据结构 - 就像在 unique_everseen
recipe in the itertools section 中一样(逐字复制):
from itertools import filterfalse
def unique_everseen(iterable, key=None):
"List unique elements, preserving order. Remember all elements ever seen."
# unique_everseen('AAAABBBCCDAABBB') --> A B C D
# unique_everseen('ABBCcAD', str.lower) --> A B C D
seen = set()
seen_add = seen.add
if key is None:
for element in filterfalse(seen.__contains__, iterable):
seen_add(element)
yield element
else:
for element in iterable:
k = key(element)
if k not in seen:
seen_add(k)
yield element
基本上这将解决您使用 key=frozenset
:
时的问题
>>> x = [('a',1,2), ('b',3,4), ('x',5,6), ('a',2,1)]
>>> list(unique_everseen(x, key=frozenset))
[('a', 1, 2), ('b', 3, 4), ('x', 5, 6)]
这 returns 元素 原样 并且它还保持元素之间的相对顺序。
NumPy 中有一些非常有用的函数可以帮助您解决这个问题。
import numpy as np
chrs, indices = np.unique(list(map(lambda x:x[0], x)), return_index=True)
chrs, indices
>> (array(['a', 'b', 'x'],
dtype='<U1'), array([0, 1, 2]))
[x[indices[i]] for i in range(indices.size)]
>> [('a', 1, 2), ('b', 3, 4), ('x', 5, 6)]
您可以通过简单地使用 zip 来维护 frozenset 中的顺序来完成。
请试一试。
l = ['col1','col2','col3','col4']
>>> frozenset(l)
--> frozenset({'col2', 'col4', 'col3', 'col1'})
>>> frozenset(zip(*zip(l)))
--> frozenset({('col1', 'col2', 'col3', 'col4')})
以提问的问题为例:
>>> x = [('a',1,2), ('b',3,4), ('x',5,6), ('a',2,1)]
>>> frozenset(zip(*zip(x)))
--> frozenset({(('a', 1, 2), ('b', 3, 4), ('x', 5, 6), ('a', 2, 1))})
我有一个元组列表,每个元组包含一个字符串和两个整数。该列表如下所示:
x = [('a',1,2), ('b',3,4), ('x',5,6), ('a',2,1)]
该列表包含数千个这样的元组。现在,如果我想获得独特的组合,我可以按如下方式在列表中执行 frozenset
:
y = set(map(frozenset, x))
这给了我以下结果:
{frozenset({'a', 2, 1}), frozenset({'x', 5, 6}), frozenset({3, 'b', 4})}
我知道 set 是一个 unordered 数据结构,这是正常情况,但我想保留此处元素的顺序,以便之后可以将元素插入到pandas
数据框。数据框将如下所示:
Name Marks1 Marks2
0 a 1 2
1 b 3 4
2 x 5 6
没有订购 frozensets。您可以改为创建排序的元组来检查项目是否存在,如果元组不存在于集合中则添加原始元组:
y = set()
lst = []
for i in x:
t = tuple(sorted(i, key=str)
if t not in y:
y.add(t)
lst.append(i)
print(lst)
# [('a', 1, 2), ('b', 3, 4), ('x', 5, 6)]
保留第一个条目。
与其直接对 frozenset
的 set
进行操作,不如将其用作辅助数据结构 - 就像在 unique_everseen
recipe in the itertools section 中一样(逐字复制):
from itertools import filterfalse
def unique_everseen(iterable, key=None):
"List unique elements, preserving order. Remember all elements ever seen."
# unique_everseen('AAAABBBCCDAABBB') --> A B C D
# unique_everseen('ABBCcAD', str.lower) --> A B C D
seen = set()
seen_add = seen.add
if key is None:
for element in filterfalse(seen.__contains__, iterable):
seen_add(element)
yield element
else:
for element in iterable:
k = key(element)
if k not in seen:
seen_add(k)
yield element
基本上这将解决您使用 key=frozenset
:
>>> x = [('a',1,2), ('b',3,4), ('x',5,6), ('a',2,1)]
>>> list(unique_everseen(x, key=frozenset))
[('a', 1, 2), ('b', 3, 4), ('x', 5, 6)]
这 returns 元素 原样 并且它还保持元素之间的相对顺序。
NumPy 中有一些非常有用的函数可以帮助您解决这个问题。
import numpy as np
chrs, indices = np.unique(list(map(lambda x:x[0], x)), return_index=True)
chrs, indices
>> (array(['a', 'b', 'x'],
dtype='<U1'), array([0, 1, 2]))
[x[indices[i]] for i in range(indices.size)]
>> [('a', 1, 2), ('b', 3, 4), ('x', 5, 6)]
您可以通过简单地使用 zip 来维护 frozenset 中的顺序来完成。 请试一试。
l = ['col1','col2','col3','col4']
>>> frozenset(l)
--> frozenset({'col2', 'col4', 'col3', 'col1'})
>>> frozenset(zip(*zip(l)))
--> frozenset({('col1', 'col2', 'col3', 'col4')})
以提问的问题为例:
>>> x = [('a',1,2), ('b',3,4), ('x',5,6), ('a',2,1)]
>>> frozenset(zip(*zip(x)))
--> frozenset({(('a', 1, 2), ('b', 3, 4), ('x', 5, 6), ('a', 2, 1))})