Получение первых n уникальных элементов из списка Python - PullRequest
0 голосов
/ 21 декабря 2018

У меня есть список Python, где элементы могут повторяться.

>>> a = [1,2,2,3,3,4,5,6]

Я хочу получить первые n уникальные элементы из списка.Итак, в этом случае, если мне нужны первые 5 уникальных элементов, они будут:

[1,2,3,4,5]

Я пришел к решению с использованием генераторов:

def iterate(itr, upper=5):

    count = 0
    for index, element in enumerate(itr):
        if index==0:
            count += 1
            yield element

        elif element not in itr[:index] and count<upper:
            count += 1
            yield element

Используется:

>>> i = iterate(a, 5)
>>> [e for e in i]
[1,2,3,4,5]

Я сомневаюсь, что это самое оптимальное решение.Есть ли альтернативная стратегия, которую я могу реализовать, чтобы написать ее более питонно и эффективно?

Ответы [ 12 ]

0 голосов
/ 10 мая 2019
a = [1,2,2,3,3,4,5,6]

from collections import defaultdict
def function(lis,n):
    dic = defaultdict(int)

    sol=set()

    for i in lis:
            try:
                if dic[i]:
                    pass
                else:
                    sol.add(i)
                    dic[i]=1
                    if len(sol)>=n:
                        break
            except KeyError:
                pass

    return list(sol)

print(function(a,3))

выход

[1, 2, 3]
0 голосов
/ 22 декабря 2018

Почему бы не использовать что-то подобное?

>>> a = [1, 2, 2, 3, 3, 4, 5, 6]
>>> list(set(a))[:5]
[1, 2, 3, 4, 5]
0 голосов
/ 13 марта 2019

Пример списка:

a = [1, 2, 2, 3, 3, 4, 5, 6]

Функция возвращает все или количество уникальных элементов, необходимых из списка

1-й аргумент - список для работы, 2-й аргумент (необязательно) - количество уникальных элементов(по умолчанию - None - это означает, что будут возвращены все уникальные элементы)

def unique_elements(lst, number_of_elements=None):
    return list(dict.fromkeys(lst))[:number_of_elements]

Вот пример того, как это работает.Имя списка - «a», и нам нужно получить 2 уникальных элемента:

print(unique_elements(a, 2))

Вывод:

output

0 голосов
/ 21 декабря 2018

Предполагая, что элементы упорядочены, как показано, это возможность повеселиться с функцией groupby в itertools:

from itertools import groupby, islice

def first_unique(data, upper):
    return islice((key for (key, _) in groupby(data)), 0, upper)

a = [1, 2, 2, 3, 3, 4, 5, 6]

print(list(first_unique(a, 5)))

Обновлен для использования islice вместо enumerate для @juanpa.arrivillaga.Вам даже не нужно set, чтобы отслеживать дубликаты.

0 голосов
/ 22 декабря 2018

Дано

import itertools as it


a = [1, 2, 2, 3, 3, 4, 5, 6]

Код

Простое понимание списка (аналогично ответу @ cdlane).

[k for k, _ in it.groupby(a)][:5]
# [1, 2, 3, 4, 5]

В качестве альтернативы в Python 3.6 +:

list(dict.fromkeys(a))[:5]
# [1, 2, 3, 4, 5]
0 голосов
/ 21 декабря 2018

Если ваши объекты имеют хэшируемый (int с хэшируемый), вы можете написать вспомогательную функцию, используя fromkeys метод из collections.OrderedDict класс (или начиная с Python3.7 обычный dict, так как они стали официально упорядоченными) как

from collections import OrderedDict


def nub(iterable):
    """Returns unique elements preserving order."""
    return OrderedDict.fromkeys(iterable).keys()

, и тогда реализация iterate может быть упрощенана

from itertools import islice


def iterate(itr, upper=5):
    return islice(nub(itr), upper)

или если вы хотите всегда list в качестве вывода

def iterate(itr, upper=5):
    return list(nub(itr))[:upper]

Улучшения

Как упомянул @Chris_Rands, это решение проходит через всю коллекцию, и мыможно улучшить это, написав nub утилиту в виде генератора , как другие уже сделали:

def nub(iterable):
    seen = set()
    add_seen = seen.add
    for element in iterable:
        if element in seen:
            continue
        yield element
        add_seen(element)
0 голосов
/ 21 декабря 2018

Вот подход Pythonic, использующий itertools.takewhile():

In [95]: from itertools import takewhile

In [96]: seen = set()

In [97]: set(takewhile(lambda x: seen.add(x) or len(seen) <= 4, a))
Out[97]: {1, 2, 3, 4}
0 голосов
/ 21 декабря 2018

Вы можете использовать OrderedDict или, начиная с Python 3.7, обычный dict, поскольку они реализованы для сохранения порядка вставки.Обратите внимание, что это не будет работать с сетами.

N = 3
a = [1, 2, 2, 3, 3, 3, 4]
d = {x: True for x in a}
list(d.keys())[:N]
0 голосов
/ 21 декабря 2018

Есть действительно удивительные ответы на этот вопрос, которые бывают быстрыми, компактными и блестящими!Причина, по которой я привожу здесь этот код, состоит в том, что я считаю, что существует множество случаев, когда вам не нужно терять 1 микросекунду, или вам не нужны дополнительные библиотеки в вашем коде для единовременного решения простой задачи.

a = [1,2,2,3,3,4,5,6]
res = []
for x in a:
    if x not in res:  # yes, not optimal, but doesnt need additional dict
        res.append(x)
        if len(res) == 5:
            break
print(res)
0 голосов
/ 21 декабря 2018

Использование set с sorted+ key

sorted(set(a), key=list(a).index)[:5]
Out[136]: [1, 2, 3, 4, 5]
...