5

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

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 是一个无序的数据结构,这是正常情况,但我想在这里保留元素的顺序,以便之后我可以将元素插入pandas数据框中。数据框将如下所示:

 Name  Marks1  Marks2
0    a       1       2
1    b       3       4
2    x       5       6
4

3 回答 3

4

您可以将其仅用作辅助数据结构,而不是直接在setof s 上操作 - 就像在itertools 部分的配方中一样(逐字复制):frozensetunique_everseen

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)]

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

于 2017-08-29T10:21:43.967 回答
1

没有用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)]

第一个条目被保留。

于 2017-08-29T10:13:18.387 回答
0

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)]
于 2017-08-29T10:55:18.580 回答