开发者

Check if the integer in a list is not duplicated, and sequential

testGroupList is a list of integer. I need to check the numbers in testGroupList is sequential and not duplicate numbers. Ignore the negative integer.

For example, [1,2,-1,2,3,4] is an error as 2 is duplicated, but [-1,3,2,4,1,5] is OK.

I implemented it as follows, and it's pretty ugly. Is there any clever way to do this?

    buff = filter(lambda x: x > 0, testGroupList) 
    maxval = max(buff) 
    for i in range(maxval): 
        id = i+1 
        val = buff.count(id) 
        if val == 1: print id, 
        elif val >= 2: print "(Test 开发者_运维问答Group %d duplicated %d times)" % (id, val), 
        elif val == 0: print "(Test Group %d missing)" % id,


For Python2.7 or 3.1 you can use Counter, although the print needs to be changed in the case of Python3

from collections import Counter
counter = Counter(x for x in testGroupList if x>=0)
minval = min(Counter) 
maxval = max(Counter)
messages={0:"(Test Group %(id)d missing)",
          1:"%(id)d",
          2:"(Test Group %(id)d duplicated %(val)d times)"}
for id in range(minval,maxval+1): 
    val = counter[id]
    print(messages[min(val,2)]%vars())

For older Python use defaultdict

from collections import defaultdict
counter = defaultdict(int)
for k in testGroupList:
    if k>=0:counter[k]+=1

minval = min(counter) 
maxval = max(counter)
messages={0:"(Test Group %(id)d missing)",
          1:"%(id)d",
          2:"(Test Group %(id)d duplicated %(val)d times)"}
for id in range(minval,maxval+1): 
    val = counter[id]
    print messages[min(val,2)]%vars(),


If you're looking for more elegant as in smaller code, then you can just do this:

buff = [x for x in testGroupList if x > 0]
for i, val in enumerate([buff.count(x) for x in xrange(1,max(buff))]):
    if val == 1: print i+1, 
    elif val > 1: print "(Test Group %d duplicated %d times)" % (i+1, val), 
    elif val == 0: print "(Test Group %d missing)" % (i+1),

which is pretty close to your original. I used i instead of id because id is a standard function in Python.


for i, v in enumerate(buff):
    if i != v - 1:
        print "MISSING OR DUPLICATE"


If you don't need fancy error reporting, then you can implement it as two simple checks:

positiveValues = [x for x in testGroupList if x > 0]
if len(positiveValues) != len(set(positiveValues)):
    print("Input has duplicate values")
elif len(positiveValues) != max(positiveValues):
    print("Input has missing values")


If you are just trying to determine a list has no duplicates, then you can create a set() with the list's elements, and compare the length of the two. Same length means no duplicates.

Determining if they are sequential can look at the difference of max and min of the list, which should be one less than the length.

A "set difference" can be used to find missing ints.

Here's some concise definitions:

def all_different(any_list):
    '''returns True if all items in the list are different.
    (Note: this assumes input is a list'''
    return len(any_list) == len(set(any_list))

def any_duplicate(any_list):
    '''returns True if any items in the list are repeated.
    (Note: this assumes input is a list'''
    return len(any_list) != len(set(any_list))

def sequential_ints(list_of_ints):
    '''returns True if input is a sequential list of ints.
    (Note: this assumes input is a list, and only of ints'''
    return len(list_of_ints)-1==max(list_of_ints)-min(list_of_ints)

def find_missing(list_of_ints):
    '''returns a list of any integers "missing", assuming 
    input was "supposed to be" sequential list of ints.
    (Note: this assumes input is a list, and only of ints'''
    return list( set(range(min(list_of_ints),max(list_of_ints)+1))-set(list_of_ints) )

This test code:

list1 = [1, 2, 3, 4, 5, 6]
print("all_different:", all_different(list1))
print("any_duplicate:", any_duplicate(list1))
print("sequential_ints:", sequential_ints(list1))
print("find_missing:   ", find_missing(list1))
print()

list2 = [1, 2, 3, 4, 5, 6, 2]
print("all_different:", all_different(list2))
print("any_duplicate:", any_duplicate(list2))
print("sequential_ints:", sequential_ints(list2))
print("find_missing:   ", find_missing(list2))
print()

list3 = [1, 3, 4, 6]
print("all_different:", all_different(list3))
print("any_duplicate:", any_duplicate(list3))
print("sequential_ints:", sequential_ints(list3))
print("find_missing:   ", find_missing(list3))

Gives:

all_different: True
any_duplicate: False
sequential_ints: True
find_missing:    []

all_different: False
any_duplicate: True
sequential_ints: False
find_missing:    []

all_different: True
any_duplicate: False
sequential_ints: False
find_missing:    [2, 5]
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜