6

Write a function that accepts an input list and returns a new list which contains only the unique elements (Elements should only appear one time in the list and the order of the elements must be preserved as the original list. ).

def unique_elements (list):
    new_list = []
    length = len(list)
    i = 0
    while (length != 0):
        if (list[i] != list [i + 1]):
            new_list.append(list[i])
        i = i + 1
        length = length - 1
    '''new_list = set(list)'''
    return (new_list)

#Main program
n = int(input("Enter length of the list: "))
list = []
for i in range (0, n):
    item = int(input("Enter only integer values: "))
    list.append(item)
print ("This is your list: ", list)
result = unique_elements (list)
print (result)

I am stuck with this error:

IndexError: list index out of range

7
  • 4
    Just a quick note, list is a keyword Commented Feb 21, 2016 at 7:13
  • @Obsidian no list is not a keyword Commented Feb 21, 2016 at 7:17
  • 1
    List is the name of a builtin. You can redefine it, but it is not recommended. Commented Feb 21, 2016 at 7:19
  • 1
    @helloV Sorry. Meant a builtin function Commented Feb 21, 2016 at 7:20
  • 3
    Your list index range error is due to the fact that i is being iterated over all element indices, so when it's on the last element, i+1 will be out of bounds. But a bigger problem is that you're only checking adjacent elements for duplicates. What if your list is [1, 2, 1]? Your algorithm will return all three elements, which I don't believe you want. Commented Feb 21, 2016 at 7:22

10 Answers 10

18

This is the simplest way to do it:

a = [1, 2, 2, 3]
b = []
for i in a:
    if i not in b:
        b.append(i)
print (b)
[1, 2, 3]
Sign up to request clarification or add additional context in comments.

2 Comments

The question is what is the issue with the code? Not asking a new solution.
@helloV my understanding of the OP is to come up with an answer to the problem which is: Write a function that accepts an input list and returns a new list which contains only the unique elements (Elements should only appear one time in the list and the order of the elements must be preserved as the original list. ).
3

The problem with your code is that you are looping length times but checking list[i] with list[i+1], thus accessing an element past the end of the input list (e.g. in a list with 6 elements there are 6-1=5 pairs of consecutive elements).

A second issue with your code is that an input with only one element [1] should give as output [1] even if this element is not different from any other. The input text means you should remove elements that are equal to other elements already present, not that you should keep elements that are different from the next one.

Another issue is that you're only checking for consecutive duplicates i.e. given the input list [1, 2, 1, 2] your logic wouldn't detect any duplication... looks like the exercise instead requires in this case as output of [1, 2].

A trace for a simple algorithm to do this is

for each element in input
   if the element has not been included in output
       add the element to the end of output

Note also that to check if an element is present in a list Python provides the in operator (e.g. if x in output: ...) that can save you an explicit loop for that part.

As a side note naming an input parameter list is considered bad practice in Python because list is the name of a predefined function and your parameter is hiding it.

Comments

2

O(n) solution without using a set:

>>> from collections import Counter, OrderedDict
>>> class OrderedCounter(Counter, OrderedDict):
...     pass
... 
>>> lst = [1, 2, 2, 3, 4, 5, 4]
>>> [x for x,c in OrderedCounter(lst).items() if c==1]
[1, 3, 5]

Comments

2
l = [1, 2, 2, 3,4,5,6,5,7,8]
myList = []
[ myList.append(item) for item in l if item not in myList]
print(myList)

Comments

1

One line implementation:

list = [100, 3232, 3232, 3232, 57, 57, 90]
new_list = []

[new_list.append(x) for x in list if x not in new_list]

print(new_list)

Prints:

[100, 3232, 57, 90]

1 Comment

It's a bad idea to use a list comprehension just to avoid the extra lines of a regular for loop and if statement. You build an extra list of None values, only to throw it away again.
1

The problematic line is > if (list[i] != list [i + 1]): < (6th line in your code).

Reason: Imagine your list has got 4 elements.

Eg: mylist = [ 1, 2,2,3].

mylist[i] != mylist [i + 1]

In the last iteration 'i' will be 4 , so i + 1 will be 5.

There is no such 5th index in that list, because list indexes are counted from zero.

mylist[0] = 1

mylist[1] = 2

mylist[2] = 2

mylist[3] = 3

mylist[4] = No Index

mylist[5] = No Index

    def unique_elements (list):
        new_list = []

   # Replace the while with a for loop** 

        for i in list:
          if i not in new_list:
            new_list.append(i)


        return (new_list)

    #Main program
    n = int(input("Enter length of the list: "))
    list = []
    for i in range (0, n):
        item = int(input("Enter only integer values: "))
        list.append(item)
    print ("This is your list: ", list)
    result = unique_elements (list)
    print (result)

Comments

0

Use of collections is best IMO, Accepted answer is simplest, Adding another approach using dict where you can check frequency as well,


text = [100, 3232, 3232, 3232, 57, 57, 90]
# create empty dictionary
freq_dict = {}
 
# loop through text and count words
for word in text:
    # set the default value to 0
    freq_dict.setdefault(word, 0)
    # increment the value by 1
    freq_dict[word] += 1
 
unique_list = [key for key,value in freq_dict.items()]

print(unique_list )

print(freq_dict )
[100, 3232, 57, 90]
{100: 1, 3232: 3, 57: 2, 90: 1}

[Program finished] 

You can also print by values based on requirements.

Comments

0

So if you are at the last element, then if (list[i] != list [i + 1]): will try to take a value out of the list which is not present there and that is why the error is showing that the list is out of range.

1 Comment

This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From Review
-2

You can work this out using sets and set comprehension syntax is in most cases overlooked. Just as lists sets can also be generated using comprehension.

elements = [1, 2, 3, 3, 5, 7, 8, 7, 9]
unique_elements = {element for element in elements}
print(unique_elements)

Comments

-2

Found an easier approach for people on Python 3.7.

Using a dictionary:

list(dict.fromkeys(mylist))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.