如何在列表中找到第二小的唯一数字?

3

我需要创建一个函数,返回第二小的唯一数字。这意味着如果list1 = [5,4,3,2,2,1],我需要返回3,因为2不是唯一的。

我尝试过:

def second(list1):
    result = sorted(list1)[1]
    return result

and

def second(list1):
    result = list(set((list1)))
    return result

但它们都返回2。
编辑1:
谢谢大家!我使用最终代码使其工作:
def second(list1):
    b = [i for i in list1 if list1.count(i) == 1]
    b.sort()
    result = sorted(b)[1]
    return result

编辑2:

好的,大家有点困惑了。我的教授告诉我,如果list1 = [1,1,2,3,4],应该返回2,因为2仍然是第二小的数字,而如果list1 = [1,2,2,3,4],则应该返回3。 在list1 = [1,1,2,3,4]的情况下,编辑1中的代码不起作用。 我想我需要做这样的事情:

如果列表中有重复数字,则删除所有重复项并返回第二个数字。 否则,如果重复数字位置不在list1 [0]中,则只需使用EDIT1中的代码。


3
你尝试了什么来确定一个数是否唯一? - DSM
我的第二次尝试是消除列表中的重复项...然后我知道我可以使用sorted(list1)[2]来返回3。但是,我需要编写通用代码,其中列表可能是[5,4,4,3,3,2,2,1],我需要返回5,但我不能使用sorted(),因为我不知道要放什么在方括号里。(sorted(list1)[???]) - ProgrammingPikachu
set(list1) 不会删除出现多次的值。{3,4,4} => {3,4},而不是 {3} - Akavall
2
你进行了两次排序。一次是使用 b.sort,第二次是使用 sorted(b) - jamylak
5个回答

3

不使用任何高级技巧,为什么不先获取一个唯一值列表,对其进行排序,然后获取第二个列表项呢?

a = [5,4,3,2,2,1] #second smallest is 3
b = [i for i in a if a.count(i) == 1]
b.sort()
>>>b[1]
3


a = [5,4,4,3,3,2,2,1] #second smallest is 5
b = [i for i in a if a.count(i) == 1]
b.sort()
>>> b[1]
5

显然,您需要测试列表中至少有两个唯一的数字。换句话说,请确保 b 的长度至少为2。


嘿,谢谢!我使用了你的代码,在添加了一些行后得到了我需要的结果。 - ProgrammingPikachu

2
  1. 删除非唯一元素 - 使用 sort/itertools.groupbycollections.Counter
  2. 使用 O(n) 的 min 函数来确定最小值,而不是使用 O(nlogn) 的 sort 函数。(在任何情况下,如果您使用的是 groupby,数据已经被排序) 我错过了 OP 想要获得第二个最小值的事实,因此在这种情况下排序仍然是更好的选择

示例代码

使用 Counter

>>> sorted(k for k, v in Counter(list1).items() if v == 1)[1]
1

使用 Itertools

>>> sorted(k for k, g in groupby(sorted(list1)) if len(list(g)) == 1)[1]
3

0

好的,这里在列表上使用set()是没有帮助的。它不会清除重复的元素。我的意思是:

l1=[5,4,3,2,2,1]
print set(l1)

打印

[0, 1, 2, 3, 4, 5]

这里不是在删除重复元素,而是使列表变得唯一

在你的例子中,你想要删除所有重复的元素。 尝试像这样做。

l1=[5,4,3,2,2,1]
newlist=[]
for i in l1:
    if l1.count(i)==1:
    newlist.append(i)
print newlist 

在这个例子中,它会打印出

这个


[5, 4, 3, 1]

然后你可以使用heapq来获取列表中第二大的数字,就像这样

print heapq.nsmallest(2, newlist)[-1]

导入: import heapq,上面的代码片段为您打印3。这应该就可以了。干杯!


1
我喜欢使用heapq的想法,但是你使用l1.count()而不是适合在O(N)时间内进行计数的数据结构(例如collections.Counter)甚至是O(NlogN)(itertools.groupby + sort)来做计数,从而抵消了你的解决方案的任何算法优势。使用l1.count()使这成为一个O(N^2)算法 :-)。 - mgilson
是的,可以使用Collections来获得更好的性能。下次会使用它们。感谢@mgilson的指导! - sameera sy
“Okay,everyone says use a set() on a list”中的“everyone”是指谁?没有人建议使用set()来获取唯一值。 - BlivetWidget
@BlivetWidget 我所说的“每个人”是指如果你在谷歌上搜索去重或清除重复项,有7/10的人建议使用set()函数。但是在这里没有人提出过这种方法!不管怎样,我会在这里进行更改!谢谢! - sameera sy

0
这里有一种更高级的方法,它不使用计数(这意味着在大型数据集上应该具有显着更好的性能)。
from collections import defaultdict

def getUnique(data):
    dd = defaultdict(lambda: 0)
    for value in data:
        dd[value] += 1
    result = [key for key in dd.keys() if dd[key] == 1]
    result.sort()
    return result

a = [5,4,3,2,2,1]
b = getUnique(a)
print(b)
# [1, 3, 4, 5]
print(b[1])
# 3

0

好的,小伙子们!在你们的帮助下,我得到了可工作的代码,并且你们帮助我思考正确的方向。这段代码是有效的:

`def second(list1):
    if len(list1)!= len(set(list1)):
         result = sorted(list1)[2]
        return result
    elif len(list1) == len(set(list1)):
        result = sorted(list1)[1]
        return result`

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接