保持冻结集中元素的顺序

mlR*_*cks 5 python python-2.7 pandas frozenset

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

x = [('a',1,2), ('b',3,4), ('x',5,6), ('a',2,1)]
Run Code Online (Sandbox Code Playgroud)

该列表包含数千个这样的元组。现在,如果我想获得独特的组合,我可以frozenset按如下方式在我的列表中进行:

y = set(map(frozenset, x))
Run Code Online (Sandbox Code Playgroud)

这给了我以下结果:

{frozenset({'a', 2, 1}), frozenset({'x', 5, 6}), frozenset({3, 'b', 4})}
Run Code Online (Sandbox Code Playgroud)

我知道 set 是一个无序的数据结构,这是正常情况,但我想在此处保留元素的顺序,以便此后可以将元素插入到pandas数据帧中。数据框将如下所示:

 Name  Marks1  Marks2
0    a       1       2
1    b       3       4
2    x       5       6
Run Code Online (Sandbox Code Playgroud)

MSe*_*ert 6

您可以将其仅用作辅助数据结构,而不是直接对setof进行操作 - 就像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
Run Code Online (Sandbox Code Playgroud)

基本上,当您使用以下命令时,这可以解决问题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)]
Run Code Online (Sandbox Code Playgroud)

这会按原样返回元素,并且还会维护元素之间的相对顺序。

  • 当然,如果 `x` 是一个 `pd.Series` 对象,您可以利用它并使用 `x[x.apply(frozenset).drop_duplicates().index]` 来利用 pandas 的所有优点。 。 (3认同)
  • 不过,作为另一个答案可能是有用的 - 考虑到问题是用 pandas 标记的:) 就像你说的:速度很好,但有时最好使用现有的函数而不是滚动自己的函数。 (2认同)