Python 保持冻结集中元素的顺序

Python 保持冻结集中元素的顺序,python,python-2.7,pandas,frozenset,Python,Python 2.7,Pandas,Frozenset,我有一个元组列表,每个元组包含一个字符串和两个整数。列表如下所示: x = [('a',1,2), ('b',3,4), ('x',5,6), ('a',2,1)] Name Marks1 Marks2 0 a 1 2 1 b 3 4 2 x 5 6 该列表包含数千个这样的元组。现在,如果我想获得独特的组合,我可以按如下方式执行列表中的frozenset: y = set(map(frozense

我有一个元组列表,每个元组包含一个字符串和两个整数。列表如下所示:

x = [('a',1,2), ('b',3,4), ('x',5,6), ('a',2,1)]
 Name  Marks1  Marks2
0    a       1       2
1    b       3       4
2    x       5       6
该列表包含数千个这样的元组。现在,如果我想获得独特的组合,我可以按如下方式执行列表中的
frozenset

y = set(map(frozenset, x))
这给了我以下结果:

{frozenset({'a', 2, 1}), frozenset({'x', 5, 6}), frozenset({3, 'b', 4})}
我知道集合是一个无序的数据结构,这是正常情况,但我想在这里保留元素的顺序,以便以后可以将元素插入到数据帧中。数据帧将如下所示:

x = [('a',1,2), ('b',3,4), ('x',5,6), ('a',2,1)]
 Name  Marks1  Marks2
0    a       1       2
1    b       3       4
2    x       5       6

没有定购的冷冻套装。您可以创建已排序的元组来检查是否存在项,如果元组在集合中不存在,则添加原始元组:

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
集合上操作,您只能将其用作辅助数据结构,如(复制的逐字):

当您使用
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)]

这将按原样返回元素,并保持元素之间的相对顺序。

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)]
将numpy导入为np
chrs,indexes=np.unique(list(map(lambda x:x[0],x)),return_index=True)
指标
>>(数组(['a','b','x'],

dtype='你真的有(a,1,2)被表示为(2,a,1)并且它们应该被视为重复的情况吗?因为似乎仅仅使用
pd.Series(x).unique()
就是你想要的……否则(a,1,2)肯定与(a,2,1)相同-如果是的话-哪一个被保留(a,1,2)或(a,2,1)?(a,1,2)和(a,2,1)被视为相同的,只有第一次出现的情况应该被保留,即(a,1,2)Youch-因此根据数据的输入,您的输出将不同…当然,如果
x
pd.Series
对象,您可以利用它并使用
x[x.apply(frozenset).drop_duplicates().index]
要充分利用所有的优点…即使要短得多-也会慢一些(取决于
x的长度
慢得多或慢一点)。至少如果我没记错的话。我使用itertools配方,每个循环37.3ns,每个循环12 us,使用apply/drop_duplicates/index方法。所以是的-只有一点区别:)呸…在
pd.DataFrame((*row,frozenset(row))方面运气不太好((*row,frozenset(row))对于x中的行),列=['M1','M2','M3','K'])。drop_duplicates(subset='K'])
也可以-虽然速度没有那么慢,并且最终得到了所需的数据帧…我想我现在就放弃:)可能是另一个有用的答案-考虑到问题被标记为pandas:)就像你说的:速度很好,但有时只使用现有函数而不是滚动自己的函数更好。