简体   繁体   中英

How to check elements in a list WITHOUT using for loops?

Apologies if the title of the question is phrased badly. I am currently trying to make a function that takes in a list of integers from 1 to n, where n is the length of the list. The function should return the first value that is repeated in the list. Duplicates are NOT always next to one another. If one or more integers is less than 1 or if it is not a list, the function should return -1. If there are no duplicates, return 0.

This is my current code:

def find_duplicates(ls):
    if type(ls) != list:
        return -1

    non_dupe = []
    i = 0
    while i < len(ls):
        if ls[i] < 1:
            return -1
            break
        if ls.count(i) > 1:
            return i
            break
        else:
            non_dupe.append(i)
            i += 1

    if len(non_dupe) == len(ls):
        return 0

While this code works for a majority of test cases, it doesn't seem to pass

print(find_duplicates([1, 2, 2, 0]))

as it returns 2 instead of the expected -1. I am relatively new to Python and I can't seem to be able to fix this error. I've tried searching for ways to counter this problem but I am not allowed to use for loops to check through a list. Any help is greatly appreciated.

EDIT: I am not allowed to use any of the following but anything else is accepted.

  1. for loops
  2. min() / max()
  3. enumerate() / zip ()
  4. sort()
  5. negative indexing eg ls[-1]
  6. list slicing

Problem is beacause you are breaking while loop when find a duplicated. In that case, function is finding first the duplicated.

Try this:

def find_duplicates(ls):
    if type(ls) is not list:
        return -1
    duplicated = 0
    i = 0
    while i < len(ls):
        if ls[i] < 1:
            return -1
        if ls.count(ls[i]) > 1 and duplicated == 0
            duplicated = ls[i]
        i += 1
    return duplicated

Your test case returns 2 because 2 stay at lower indexes comparing to 0 .

I would suggest to sort the list before moving on:

def find_duplicates(ls):
    if type(ls) != list:
        return -1

    sorted_list = ls.sorted()           #Assign sorted `ls` to another variable, while keeping the order of `ls` intact
    non_dupe = []
    i = 0
    
    while i < len(ls):
        if ls[i] < 1:
            return -1
            break
        if ls.count(i) > 1:
            return i
            break
        else:
            non_dupe.append(i)
            i += 1
    
    if len(non_dupe) == len(ls):
        return 0

Another method I would recommend is using set - a built-in data type of Python. Maybe you should consider trying this approach later on when all test cases are passed. Have a look at this Tutorial for set usage: https://www.w3schools.com/python/python_sets.asp .

Your code returns a duplicate prematurely ; traversing the list, the function first finds 2 as a duplicate, return it, and halts the function immediately. But it has not seen the 0 at the end.

So, you need to let the function see the list all the way towards the end, looking for a negative number. If a negative number is found along the way, you can halt the function. If it does not see a negative number until the end, then let it return the duplicate value:

def find_duplicates(ls):
    if not isinstance(ls, list): # check whether ls is a list
        return -1

    dup = 0
    seen = [] # list of numbers seen so far
    i = 0 # index

    while i < len(ls):
        if ls[i] < 1: # if a negative number is found, return -1
            return -1
        if ls[i] in seen and dup == 0:
            dup = ls[i]
        seen.append(ls[i])
        i += 1
    return dup

print(find_duplicates([1, 2, 2, 0])) # -1
print(find_duplicates([1, 1, 2, 2, 3])) # 1

You were very close. Try this:

def find_duplicates(ls):
    if type(ls) != list:
        return -1   
    non_dupe = []
    i = 0
    while i < len(ls):
        if ls[i] < 1:
            return -1
        elif ls[i] in non_dupe:
            return ls[i]
        else:
            non_dupe.append(i)
        i += 1
    return 0
my_list = [1,2,2,0]

result = list(set(filter(lambda x: my_list.count(x) > 1 , my_list)))

# Result =>  [2]

I hope this solves your problem

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM