У меня есть список кортежей, каждый из которых содержит одну строку и два целых числа. Список выглядит так:

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

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

 Name  Marks1  Marks2
0    a       1       2
1    b       3       4
2    x       5       6
4
mlRocks 29 Авг 2017 в 13:10

3 ответа

Лучший ответ

Вместо того чтобы работать с set из frozenset напрямую, вы можете использовать это только как вспомогательную структуру данных - как в unique_everseen рецепт в разделе itertools (дословно скопировано):

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

Это возвращает элементы как есть , а также поддерживает относительный порядок между элементами.

3
MSeifert 29 Авг 2017 в 10:21

В 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)]
0
misakawa 29 Авг 2017 в 10:55

Нет заказов с 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)]

Первая запись сохраняется.

0
Moses Koledoye 29 Авг 2017 в 10:23