2

I have a list and a for loop such as these:

mylist = ['foo','foo','foo','bar,'bar','hello']
for item in mylist:
    cp = mylist.count(item)
    print("You "+item+" are present in "+str(cp)+" copy(ies)")

Output:

You foo are present in 3 copy(ies)
You foo are present in 3 copy(ies)
You foo are present in 3 copy(ies)
You bar are present in 2 copy(ies)
You bar are present in 2 copy(ies)
You dude are present in 1 copy(ies)

Expected output:

You foo are present in 3 copy(ies)
You bar are present in 2 copy(ies)
You dude are present in 1 copy(ies)

The idea is thus to skip a variable number of iterations within the for loop, using something like this script (not working):

for item in mylist:
    cp = mylist.count(item)
    print("You "+item+" are present in "+str(cp)+" copy(ies)")
    continue(cp)

The script would thus "jump" cp elements in the for loop at every round and start doing again what it is asked at the item item + cp.

I know that you can use continue to skip multiple iterations (such as in this post) but I cannot figure out how to use continue to skip a variable number of iterations.

Thanks for your answer! :)


Edit: similar items are always next to each other.

2
  • is this list always sorted/grouped e.g. same elements are always together? Commented Jun 14, 2016 at 10:09
  • @Jerzyk yes indeed! Commented Jun 14, 2016 at 10:11

7 Answers 7

5

You could use a Counter:

from collections import Counter

mylist = ['foo','foo','foo','bar','bar','hello']
c = Counter(mylist)
for item, cp in c.items():
    print("You "+item+" are present in "+str(cp)+" copy(ies)")
Sign up to request clarification or add additional context in comments.

3 Comments

Counter object has no attribute iteritems
@pythad this is python 2 not 3. Use items() in 3
Updated answer to use items as that will work in both 2 and 3. Thanks for the comment.
3

You can use collections.Counter for your job:

>>> from collections import Counter
>>> Counter(['foo', 'foo', 'bar'])
Counter({'foo': 2, 'bar': 1})

Thus,

count_dict = Counter(mylist)
for item in count_dict:
    print("You "+item+" are present in "+str(count_dict[item[)+" copy(ies)")

Comments

3

Since the elements are consecutive, you could use a groupby which would group the consecutive strings, it is just a matter of summing the length of each group to get the count:

from itertools import groupby
mylist = ['foo','foo','foo','bar','bar','hello']

for k,v in groupby(mylist):
    print("You {} are present in {} copy(ies)".format(k, sum(1 for _ in v)))

Output:

You foo are present in 3 copy(ies)
You bar are present in 2 copy(ies)
You hello are present in 1 copy(ies)

The most efficient way to generally get counts would be to use the dictionary logic like a Counter provided in the other answers, if you want to keep order you could use an OrderedDict to do the counting:

from collections import OrderedDict
mylist = ['foo','foo','foo','bar','bar','hello']
od = OrderedDict()
for ele in mylist:
    od.setdefault(ele, 0)
    od[ele] += 1

for tup in od.items():
    print("You {} are present in {} copy(ies)".format(*tup))

Which would output the same:

You foo are present in 3 copy(ies)
You bar are present in 2 copy(ies)
You hello are present in 1 copy(ies)

Both the groupby and the dict logic are O(n), using your list.count is quadratic.

Comments

2

You can also do it this way

mylist = ['foo','foo','foo','bar','bar','hello']
prev = None
for item in mylist:
    if item != prev:
        cp = mylist.count(item)
        print("You "+item+" are present in "+str(cp)+" copy(ies)")
        prev = item

hope it may help !

Comments

2

You can get the unique elements of a list using set

mylist = ['foo','foo','foo','bar','bar','hello']
uniq_list = set(my_list)
for item in uniq_list:
    cp = mylist.count(item)
    print("You "+item+" are present in "+str(cp)+" copy(ies)")

Output:

You bar are present in 2 copy(ies)

You hello are present in 1 copy(ies)

You foo are present in 3 copy(ies)

5 Comments

This is O(n^2) as opposed to O(n) using a Counter
I am aware of that but the question was not to find the fastest solution but how to do it. In case the list gets really long, a different approach would make certainly make sense.
this also creates a new set for every iteration.
At the time of my comment this had two more votes than the Counter approach so for future readers it is worth pointing out
@Padraic Cunningham: Your approach is certainly more flexible and faster, +1.
1
mylist = ['foo','foo','foo','bar','bar','hello']
last = None
for item in mylist:
    if item is last:
        continue

    last = item
    cp = mylist.count(item)
    print("You "+item+" are present in "+str(cp)+" copy(ies)")

This assumes that the list is ordered so that identical objects are next to each other.

Comments

1

set and list counts would do the trick:

mylist = ['foo','foo','foo','bar','bar','hello']
for item in set(mylist):
    print("You "+item+" are present in "+str(mylist.count(item))+" copy(ies)")

output:

You foo are present in 3 copy(ies)
You bar are present in 2 copy(ies)
You hello are present in 1 copy(ies)

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.