从python中的列表中获取唯一值

时间:2012-10-15 14:05:37

标签: python

我想从以下列表中获取唯一值:

[u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']

我需要的输出是:

[u'nowplaying', u'PBS', u'job', u'debate', u'thenandnow']

此代码有效:

output = []
for x in trends:
    if x not in output:
        output.append(x)
print output

我应该使用更好的解决方案吗?

29 个答案:

答案 0 :(得分:832)

首先正确声明您的列表,用逗号分隔。您可以通过将列表转换为集合来获取唯一值。

mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
myset = set(mylist)
print(myset)

如果您将其进一步用作列表,则应通过执行以下操作将其转换回列表:

mynewlist = list(myset)

另一种可能性,可能更快,就是从头开始使用一个集合而不是列表。然后你的代码应该是:

output = set()
for x in trends:
    output.add(x)
print(output)

正如已经指出的那样,这些集合不保持原始顺序。如果您需要,您应该查看ordered set

答案 1 :(得分:263)

与我使用的类型保持一致:

mylist = list(set(mylist))

答案 2 :(得分:80)

您的输出变量是什么类型的?

Python sets就是您所需要的。声明输出如下:

output = set([]) # initialize an empty set

您已准备好使用output.add(elem)添加元素,并确保它们是唯一的。

警告:设置不要保留列表的原始顺序。

答案 3 :(得分:76)

如果我们需要保持元素顺序,那么:

used = set()
mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
unique = [x for x in mylist if x not in used and (used.add(x) or True)]

使用reduce并且没有临时used var。

的另一个解决方案
mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
unique = reduce(lambda l, x: l.append(x) or l if x not in l else l, mylist, [])

更新 - 2019年3月

第三个解决方案,它是一个整洁的解决方案,但由于.index是O(n),因此很慢。

mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
unique = [x for i, x in enumerate(mylist) if i == mylist.index(x)]

更新 - 2016年10月

使用reduce的另一种解决方案,但这次没有.append,这使得它更具人性化且易于理解。

mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
unique = reduce(lambda l, x: l+[x] if x not in l else l, mylist, [])
#which can also be writed as:
unique = reduce(lambda l, x: l if x in l else l+[x], mylist, [])

注意:请记住,我们获得了更多人类可读性,脚本更难以理解。

import timeit

setup = "mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']"

#10x to Michael for pointing out that we can get faster with set()
timeit.timeit('[x for x in mylist if x not in used and (used.add(x) or True)]', setup='used = set();'+setup)
0.4188511371612549

timeit.timeit('[x for x in mylist if x not in used and (used.append(x) or True)]', setup='used = [];'+setup)
0.6157128810882568

timeit.timeit('reduce(lambda l, x: l.append(x) or l if x not in l else l, mylist, [])', setup=setup)
1.8778090476989746

timeit.timeit('reduce(lambda l, x: l+[x] if x not in l else l, mylist, [])', setup=setup)
2.13108491897583

timeit.timeit('reduce(lambda l, x: l if x in l else l+[x], mylist, [])', setup=setup)
2.207760810852051

timeit.timeit('[x for i, x in enumerate(mylist) if i == mylist.index(x)]', setup=setup)
2.3621110916137695

回应评论

因为 @monica 问了一个关于“这是如何工作的”的好问题。对于每个有问题的人来说。我将尝试更深入地解释这是如何工作的以及这里发生的巫术;)

所以她先问:

  

我试着理解为什么unique = [used.append(x) for x in mylist if x not in used]无效。

嗯,它确实在工作

>>> used = []
>>> mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
>>> unique = [used.append(x) for x in mylist if x not in used]
>>> print used
[u'nowplaying', u'PBS', u'job', u'debate', u'thenandnow']
>>> print unique
[None, None, None, None, None]

问题是我们只是在unique变量中没有获得所需的结果,而只是在used变量中。这是因为在列表理解期间.append修改used变量并返回None

因此,为了将结果输入unique变量,并且仍然使用与.append(x) if x not in used相同的逻辑,我们需要在列表的右侧移动此.append调用理解并在左侧返回x

但是如果我们太天真并且只是跟着:

>>> unique = [x for x in mylist if x not in used and used.append(x)]
>>> print unique
[]

我们将得不到任何回报。

同样,这是因为.append方法返回None,并且这给我们的逻辑表达式提供了以下外观:

x not in used and None

这基本上总是:

    False位于x 时,
  1. 评估为usedNone不在x时,
  2. 评估为used
  3. 在这两种情况下(False / None),这将被视为falsy值,我们会得到一个空列表。

    但是当None不在x时,为什么评估为used?有人可能会问。

    好吧,因为这就是Python的short-circuit运算符works

      

    表达式x and y首先评估x;如果x为假,则其值为   回;否则,评估y并得到结果值   返回。

    因此当x未使用时(即当其True时,下一部分或表达式将被评估used.append(x)及其值None将被退回。

    但这就是我们想要从列表中获取重复项的唯一元素,我们希望.append只有当我们遇到他们的时候才会将它们列入新列表。

    所以我们真的只想在used.append(x)不在x时评估used,也许是否有办法将此None值转换为{{1}我们会好的,对吗?

    嗯,是的,这里是第二类truthy运营商所在的地方。

      

    表达式short-circuit首先评估x;如果x为真,则其值为   回;否则,评估y并得到结果值   返回。

    我们知道x or y始终为.append(x),因此,如果我们只在他旁边添加一个falsy,我们将始终获得下一部分。这就是我们写的原因:

    or

    因此我们可以评估 x not in used and (used.append(x) or True) 并获得used.append(x)仅当表达式的第一部分 {{ 1}} True

    使用(x not in used)方法可以在第二种方法中看到类似的方式。

    True

    我们在哪里:

    1. reduce附加到(l.append(x) or l) if x not in l else l #similar as the above, but maybe more readable #we return l unchanged when x is in l #we append x to l and return l when x is not in l l if x in l else (l.append(x) or l) ,并在x不在l时返回l。感谢x语句l已被评估,之后会返回or
    2. .append位于l
    3. 时,返回l不变

答案 4 :(得分:75)

您提供的示例与Python中的列表不对应。它类似于嵌套的字典,可能不是你想要的。

Python列表:

a = ['a', 'b', 'c', 'd', 'b']

要获取唯一项目,只需将其转换为一个集合(如果需要,您可以将其转换回列表):

b = set(a)
print b
>>> set(['a', 'b', 'c', 'd'])

答案 5 :(得分:40)

维持秩序:

# oneliners
# slow -> . --- 14.417 seconds ---
[x for i, x in enumerate(array) if x not in array[0:i]]

# fast -> . --- 0.0378 seconds ---
[x for i, x in enumerate(array) if array.index(x) == i]

# multiple lines
# fastest -> --- 0.012 seconds ---
uniq = []
[uniq.append(x) for x in array if x not in uniq]
uniq

订单并不重要:

# fastest-est -> --- 0.0035 seconds ---
list(set(array))

答案 6 :(得分:18)

从列表中获取唯一元素

mylist = [1,2,3,4,5,6,6,7,7,8,8,9,9,10]
  

使用集合中的简单逻辑 - 集合是唯一的项目列表

mylist=list(set(mylist))

In [0]: mylist
Out[0]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  

使用简单逻辑

newList=[]
for i in mylist:
    if i not in newList:
        newList.append(i)

In [0]: mylist
Out[0]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  

使用pop方法    - > pop删除最后一个或索引项并将其显示给用户。 video

k=0
while k < len(mylist):
    if mylist[k] in mylist[k+1:]:
        mylist.pop(mylist[k])
    else:
        k=k+1

In [0]: mylist
Out[0]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  

使用Numpy

import numpy as np
np.unique(mylist)

In [0]: mylist
Out[0]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Reference

答案 7 :(得分:15)

set - 无序的独特元素集合。元素列表可以传递给set的构造函数。因此,传递具有重复元素的列表,我们使用唯一元素进行设置并将其转换回列表然后获取具有唯一元素的列表。我不能说性能和内存开销,但我希望,它对于小型列表来说并不那么重要。

list(set(my_not_unique_list))

简单而简短。

答案 8 :(得分:12)

仅使用列表压缩的相同订单唯一列表。

            scope.adjustHeight = function () {
                console.log('adjusting height');
                var height = element.prop('scrollHeight');
                element.css('-webkit-transition', 'height 0s');
                element.css('height', height + "px");
                navbarCtrl.expanded = true;
            }

> my_list = [1, 2, 1, 3, 2, 4, 3, 5, 4, 3, 2, 3, 1] > unique_list = [ > e > for i, e in enumerate(my_list) > if my_list.index(e) == i > ] > unique_list [1, 2, 3, 4, 5] 将索引enumerates和元素i作为e

tuple返回my_list.index的第一个索引。如果第一个索引不是e,则当前迭代的i不是列表中的第一个e

修改

我应该注意,这不是一个很好的方法,在性能方面。这只是 一种只使用列表压缩来实现它的方法。

答案 9 :(得分:8)

使用Python Dictionary的基本属性:

inp=[u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
d={i for i in inp}
print d

输出将是:

set([u'nowplaying', u'job', u'debate', u'PBS', u'thenandnow'])

答案 10 :(得分:6)

set可以帮助您过滤掉重复列表中的元素。它适用于strinttuple元素,但如果您的列表包含dict或其他list元素,那么您最终会得到{ {1}}例外。

以下是处理某些(并非所有)不可清除类型的通用订单保留解决方案:

TypeError

答案 11 :(得分:6)

def get_distinct(original_list):
    distinct_list = []
    for each in original_list:
        if each not in distinct_list:
            distinct_list.append(each)
    return distinct_list

答案 12 :(得分:6)

首先,您提供的示例不是有效列表。

example_list = [u'nowplaying',u'PBS', u'PBS', u'nowplaying', u'job', u'debate',u'thenandnow']

假设上面是示例列表。然后,您可以使用以下配方作为itertools示例文档,该文档可以返回唯一值并保留您看起来需要的顺序。这里的可迭代是example_list

from itertools import ifilterfalse

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 ifilterfalse(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

答案 13 :(得分:5)

作为奖励,Counter是获取每个值的唯一值和计数的简单方法:

from collections import Counter
l = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
c = Counter(l)

答案 14 :(得分:5)

以下是获取无序或有序的独特元素的摘要。

<强>鉴于

i>=0

<强>代码

i<=MAX_INVES-1

或者在Python 3.6 +中:

from collections import OrderedDict


seq = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']

注意:列出的元素必须为hashable。另请参阅本blog post中后一个示例的详细信息。

答案 15 :(得分:4)

要从您的列表中获取唯一值,请使用以下代码:

trends = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
output = set(trends)
output = list(output)

重要: 如果列表中的任何项目不是hashablemutable类型的情况,例如listdict,则上述方法将无效。

trends = [{'super':u'nowplaying'}, u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
output = set(trends)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  TypeError: unhashable type: 'dict'

这意味着您必须确保trends列表始终只包含可散列的项目,否则您必须使用更复杂的代码:

from copy import deepcopy

try:
    trends = [{'super':u'nowplaying'}, [u'PBS',], [u'PBS',], u'nowplaying', u'job', u'debate', u'thenandnow', {'super':u'nowplaying'}]
    output = set(trends)
    output = list(output)
except TypeError:
    trends_copy = deepcopy(trends)
    while trends_copy:
        trend = trends_copy.pop()
        if trends_copy.count(trend) == 0:
            output.append(trend)
print output

答案 16 :(得分:4)

def setlist(lst=[]):
   return list(set(lst))

答案 17 :(得分:4)

除了之前的答案,即你可以将列表转换为设置,你也可以这样做

mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenadnow']
mylist = [i for i in set(mylist)]

输出

[u'nowplaying', u'job', u'debate', u'PBS', u'thenadnow']

虽然订单不会被保留。

另一个更简单的答案可能是(不使用套装)

>>> t = [v for i,v in enumerate(mylist) if mylist.index(v) == i]
[u'nowplaying', u'PBS', u'job', u'debate', u'thenadnow']

答案 18 :(得分:3)

我很惊讶到目前为止还没有人给出一个直接保留订单的答案:

<script src="//ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="//cdn.datatables.net/1.10.13/js/jquery.dataTables.min.js"></script>
<script src="//cdn.rawgit.com/DataTables/RowReorder/ce6d240e/js/dataTables.rowReorder.js"></script>
<link href="//cdn.datatables.net/1.10.13/css/jquery.dataTables.min.css" rel="stylesheet" />
<link href="//cdn.datatables.net/rowreorder/1.2.0/css/rowReorder.dataTables.min.css" rel="stylesheet"/>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />

<table id="example" class="display" width="100%" cellspacing="0">
  <thead>
    <tr>
      <th>order</th>
      <th>name</th>
      <th>country</th>
      <th>action</th>
    </tr>
  </thead>
</table>

<table id="newRow" style="display:none">
  <tbody>
    <tr>
      <td>
        <select id="selectbasic" name="selectbasic" class="form-control">
            <option value="1">option 1</option>
            <option value="2">option 2</option>
            <option value="2">option 3</option>
          </select>
      </td>
      <td>DVap
      </td>
      <td>
        www</td>
      <td><i class="fa fa-pencil-square" aria-hidden="true"></i>
        <i class="fa fa-minus-square" aria-hidden="true"></i> </td>
    </tr>
  </tbody>
</table>

<br>

<div class="pull-right">
  <a href="dashboard.html">
    <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
  </a>
  <a href="dashboard.html">
    <button type="button" class="btn btn-primary" data-dismiss="modal">Save</button>
  </a>
</div>

它将生成值,因此它不仅仅适用于列表,例如: def unique(sequence): """Generate unique items from sequence in the order of first occurrence.""" seen = set() for value in sequence: if value in seen: continue seen.add(value) yield value 。要获取列表,只需拨打unique(range(10)),如下所示:

list(unique(sequence))

它要求每个项目都是可清除的,而不仅仅是可比较的,但是Python中的大多数东西都是O(n)而不是O(n ^ 2),所以只需要很长的列表即可。< / p>

答案 19 :(得分:2)

你可以使用套装。为了清楚起见,我在解释列表和集合之间的区别。 集合是唯一元素的无序集合。列表是有序的元素集合。 所以,

    unicode_list=[u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job',u'debate', u'thenandnow']
    list_unique=list(set(unicode_list))
    print list_unique
[u'nowplaying', u'job', u'debate', u'PBS', u'thenandnow']

但是:在命名变量时不要使用list / set。它会导致错误: EX:而不是在上面使用list而不是unicode_list。

list=[u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job',u'debate', u'thenandnow']
        list_unique=list(set(list))
        print list_unique
    list_unique=list(set(list))
TypeError: 'list' object is not callable

答案 20 :(得分:2)

  1. 在代码开头时,只需将输出列表声明为空:output=[]
  2. 您可以使用此代码trends=list(set(trends))
  3. 代替您的代码

答案 21 :(得分:2)

使用set来重复删除列表,以列表形式返回

{% load static %}

<p>
<a href="{% url 'pizzas:index' %}" id="home page">Home page</a>
<a href="{% url 'pizzas:pizzas' %}">Our pizzas</a>
<button onclick="{% static 'pizzas/hack.js' %}">Hack!</button>
</p>

{% block content %} {% endblock content %}

答案 22 :(得分:1)

如果您想从列表中获取唯一元素并保持其原始顺序,那么您可以使用Python标准库中的OrderedDict数据结构:

from collections import OrderedDict

def keep_unique(elements):
    return list(OrderedDict.fromkeys(elements).keys())

elements = [2, 1, 4, 2, 1, 1, 5, 3, 1, 1]
required_output = [2, 1, 4, 5, 3]

assert keep_unique(elements) == required_output

事实上,如果你使用Python≥3.6,你可以使用普通dict

def keep_unique(elements):
    return list(dict.fromkeys(elements).keys())

在引入dicts的“紧凑”表示之后,它变得可能。看看here。虽然这“被认为是一个实施细节,不应该依赖”。

答案 23 :(得分:1)

我的解决方案是检查内容的唯一性,但保留原始顺序:

def getUnique(self):
    notunique = self.readLines()
    unique = []
    for line in notunique: # Loop over content
        append = True # Will be set to false if line matches existing line
        for existing in unique:
            if line == existing: # Line exists ? do not append and go to the next line
                append = False
                break # Already know file is unique, break loop
        if append: unique.append(line) # Line not found? add to list
    return unique

编辑: 通过使用字典键来检查存在而不是为每一行做一个完整的文件循环可能会更高效,我不会将我的解决方案用于大型集合。

答案 24 :(得分:1)

Set是有序和唯一元素的集合。因此,您可以使用以下设置获取唯一列表:

unique_list = list(set([u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']))

答案 25 :(得分:0)

我知道这是一个老问题,但这是我独特的解决方案:类继承!:

class UniqueList(list):
    def appendunique(self,item):
        if item not in self:
            self.append(item)
            return True
        return False

然后,如果要将项唯一地追加到列表中,只需在UniqueList上调用appendunique。因为它从列表继承,它基本上就像一个列表,所以你可以使用像index()等函数。因为它返回true或false,你可以找出是否追加成功(唯一项)或失败(已经在列表)。

要从列表中获取唯一的项目列表,请使用for循环将项目附加到UniqueList(然后复制到列表中)。

使用代码示例:

unique = UniqueList()

for each in [1,2,2,3,3,4]:
    if unique.appendunique(each):
        print 'Uniquely appended ' + str(each)
    else:
        print 'Already contains ' + str(each)

打印:

Uniquely appended 1
Uniquely appended 2
Already contains 2
Uniquely appended 3
Already contains 3
Uniquely appended 4

复制到列表:

unique = UniqueList()

for each in [1,2,2,3,3,4]:
    unique.appendunique(each)

newlist = unique[:]
print newlist

打印:

[1, 2, 3, 4]

答案 26 :(得分:-1)

对于长阵列

s = np.empty(len(var))

s[:] = np.nan

for  x in  set(var):

    x_positions = np.where(var==x)

    s[x_positions[0][0]]=x


sorted_var=s[~np.isnan(s)]

答案 27 :(得分:-3)

尝试此功能,它与您的代码类似,但它是一个动态范围。

def unique(a):

    k=0
    while k < len(a):
        if a[k] in a[k+1:]:
            a.pop(k)
        else:
            k=k+1



    return a

答案 28 :(得分:-3)

使用以下功能:

def uniquefy_list(input_list):
"""
This function  takes a list as input and return a list containing only unique elements from the input list

"""
output_list=[]
for elm123 in input_list:
    in_both_lists=0
    for elm234 in output_list:
        if elm123 == elm234:
            in_both_lists=1
            break
    if in_both_lists == 0:
        output_list.append(elm123)

return output_list