0

I'm trying to print all elements in a sorted list that only occur once.

My code below works but I'm sure there is a better way:

def print_unique(alist):
    i = 0
    for i in range(len(alist)):
        if i < (len(alist)-1):
            if alist[i] == alist[i+1]:
                i+=1
                if alist[i] == alist[i-1]:
                    i+=1
            elif  alist[i] == alist[i-1]:
                  i+=1    
            else:
              print alist[i]
        else:
            if alist[-1]!= alist[-2]:
                print alist[-1]

randomlist= [1,2,3,3,3,4,4,5,6,7,7,7,7,8,8,8,9,11,12,14,42]
print_unique(randomlist)

This produces

1
2
5
6
9
11
12
14
42

e.g. all values that only appear once in a row.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
yoyoed
  • 11
  • 2
  • Martijn's code is very efficient, but (like your code) it does assume that `alist` is already sorted. – PM 2Ring Jul 16 '16 at 10:10
  • 1
    @MartijnPieters OP's results only includes items that are not duplicates. Too bad the question was not well delivered. So the link to the dupe does not actually solve their problem. A slightly modified extension of the solution you proposed does it: `print [k for k, g in groupby(randomlist) if len(list(g)) == 1]` – Moses Koledoye Jul 16 '16 at 10:15
  • @MosesKoledoye: right, yes, and the OP was entirely to blame by not including a clear problem statement. – Martijn Pieters Jul 16 '16 at 10:16
  • @PM2Ring: that's what the title says can be assumed. – Martijn Pieters Jul 16 '16 at 10:17

4 Answers4

3

You could use the itertools.groupby() function to group your inputs and filter on groups that are one element long:

from itertools import groupby

def print_unique(alist):
    for elem, group in groupby(alist):
        if sum(1 for _ in group) == 1:  # count without building a new list
            print elem

or if you want to do it 'manually', track the last item seen and if you have seen it more than once:

def print_unique(alist, _sentinel=object()):
    last, once = _sentinel, False
    for elem in alist:
        if elem == last:
            once = False
        else:
            if once:
                print last
            last, once = elem, True
    if last is not _sentinel and once:
        print last

You may want to replace the print statements with yield and leave printing to the caller:

def filter_unique(alist):
    for elem, group in groupby(alist):
        if sum(1 for _ in group) == 1:  # count without building a new list
            yield elem

for unique in filter_unique(randomlist):
    print unique
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
-1

This question seems to have duplicates.

If you do not wish to preserve the order of your list, you can do

print list(set(sample_list))

You can also try,

unique_list = []
for i in sample_list:
    if i not in unique_list:
        unique_list.append(i)

EDIT:

In order to print all the elements in the list so that they appear once in a row, you can try this

print '\n'.join([str(i) for i in unique_list])

And, as @martijn-pieters mentioned it in the comments, the first code was found to be very fast compared to the second one, when I did a small benchmark. On a list of 10^5 elements, the second code took 63.66 seconds to complete whereas the first one took a mere 0.2200 seconds. (on a list generated using random.random())

Amal Rajan
  • 153
  • 1
  • 11
  • 3
    So don't answer, flag as a duplicate. And your second solution takes O(NK) time as the `unique_list` is scanned again and again to test membership. – Martijn Pieters Jul 16 '16 at 09:57
  • I still like this answer, pretty sure the OP can learn alot from it – RoadRunner Jul 16 '16 at 10:05
  • Thanks for the info, @martijn-pieters. But, I cannot mark it as duplicate with my current reputation :) – Amal Rajan Jul 16 '16 at 10:08
  • You only need 15 points to [flag posts](http://stackoverflow.com/help/privileges/flag-posts). – PM 2Ring Jul 16 '16 at 10:12
  • @PM2Ring: but more to flag as duplicate. – Martijn Pieters Jul 16 '16 at 10:24
  • @MartijnPieters: Ah, ok. I should have read the fine print. :oops: – PM 2Ring Jul 16 '16 at 10:28
  • 1
    Sorry for the misleading info in my previous comment, Amal. OTOH, even when you don't have sufficient rep to flag as duplicate, you can still do a search for dupe targets and post a link in a comment. Sure, it's not as good as a dupe flag, but it still lets potential answerers know that the question may be a dupe, and it assists those who _do_ have sufficient rep to flag or close-vote dupes. – PM 2Ring Jul 16 '16 at 10:30
  • BTW the specs of the problem have changed slightly since you wrote your answer. – PM 2Ring Jul 16 '16 at 10:33
-3

you can do by this:

print (set(YOUR_LIST))

or if you need a list use this:

print (list(set(YOUR_LIST)))
Thomas Anderson
  • 74
  • 1
  • 1
  • 9
-4

Sets are lists containing unique items. If you construct a set from the array, it will contain only the unique items:

def print_unique(alist):
   print set( alist )

The input list does not need to be sorted.

Tyler Durden
  • 11,156
  • 9
  • 64
  • 126