-4

I am looking to count the total number of duplicates in a list. Then display in alpha/numeric order the name of the list item along with the number of duplicates.

For example:

-- List
lst = [blue, green, green, yellow, yellow, yellow, orange, orange, silver, silver, silver, silver]

-- Count Number of Duplicates by X

-- Print List Item & Total Number of Occurrences for Output in Sorted list name Order

Color: blue, Total: 1
Color: green, Total: 2
Color: orange, Total: 2
Color: sliver, Total: 4
Color: yellow, Total: 3

I am able to complete the above using dictionaries, along with converting the list to a set. My goal is to complete this task all within the list type using the built in functions of Python 3.

slashdotblake
  • 64
  • 1
  • 8
  • Currently, I am trying to utilize Python as fully as possible without the need of importing modules/libraries. This task is more of a learning experience rather than how can I solve this problem in the quickest / most efficient manner. – slashdotblake Oct 07 '18 at 21:44
  • Can you [edit your question](https://stackoverflow.com/posts/52692658/edit) to include your latest attempts? Good "learning experience" involves having a go, making mistakes and seeing how to fix errors. – jpp Oct 08 '18 at 00:34
  • Why are you trying to accomplish this using only lists? – fractals Oct 08 '18 at 00:38
  • This is an exercise focused on utilizing list comprehension. From what I understand list have the most flexibility being a mutable structure. I could post my examples utilizing sets and dictionaries but there are already several threads that have very helpful examples. I felt my code would confuse the goal of my post so that is why I omitted them. When you get a chance review Slider's second example. That is exactly what I was looking to accomplish, but was getting lost in many additional methods and modules rather than solving the issue at a very basic level. – slashdotblake Oct 08 '18 at 19:43

5 Answers5

0

You can use Counter with most_common:

from collections import Counter

lst = ['blue', 'green', 'green', 'yellow', 'yellow', 'yellow', 'orange', 'orange', 'silver', 'silver', 'silver', 'silver']
freq = Counter(lst)

Now let's sort by name:

print(sorted(freq.most_common(), key=lambda x: x[0])) # [('blue', 1), ('green', 2), ('orange', 2), ('silver', 4), ('yellow', 3)]

Update

Without dictionaries or counter objects, a "manual" way to do this is to sort the list alphabetically first and then compute counts as you iterate. So something like the following:

lst = ['blue', 'green', 'green', 'yellow', 'yellow', 'yellow', 'orange', 'orange', 'silver', 'silver', 'silver', 'silver']
lst.sort()

current_color = lst[0] # assuming lst is not empty
count = 0
for c in lst:
    if c == current_color:
        count += 1
    else:
        print('Color:', current_color, 'Total:', count)
        current_color = c
        count = 1
print('Color:', current_color, ', Total:', count) # print the last color
slider
  • 12,810
  • 1
  • 26
  • 42
  • Counter converts the list into a dictionary, then a list of tuples is printed. I am looking for a solution that maintains the list structure, then uses a method such as .format along with sort/sorted to display the information in the example structure above. I am definitely going the long way here but I am looking for all the flexibility of a mutable list. – slashdotblake Oct 07 '18 at 21:30
  • @slashdotblake I see what you mean. I've added a possible solution without using dictionaries. The advantage of the second solution is that it does not use any additional space for a dict. While this is a good exercise, if space is not an issue, I would still encourage you to use a counter object for more readable code in real world applications. – slider Oct 08 '18 at 00:35
  • The second example is exactly what I was looking for to solve this problem. I looked through numerous stackoverflow post and none I could find had such a fundamentally basic solution. – slashdotblake Oct 08 '18 at 19:12
0

Why don’t you take a look at collections module? Counter function will help you to achieve your objective very simply.

cestMoiBaliBalo
  • 146
  • 2
  • 5
0

You can use itertools.groupby to combine the entries for the same color. It produces an iterator of pairs (key, values), where values is a generator for the elements matching key.

I use a degenerate sum to compute the count of the values, as in this answer, but there are other options.

import itertools

lst = "blue green green yellow yellow yellow orange orange silver silver silver silver".split()

groups = sorted(((key, sum(1 for _ in values))
                 for (key, values) in itertools.groupby(lst)))

for color, count in groups:
    print("Color: {}, Total: {}".format(color, count))
Florian Weimer
  • 32,022
  • 3
  • 48
  • 92
  • Thank you for the response. This does provide a solution but I was hoping to accomplish it without the need of itertools. This line, sum(1 for _ in values), why are you using the _ ? Is it to ignore the value of each item in the list. Can you explain this a bit further. – slashdotblake Oct 07 '18 at 21:50
  • Would you be willing to share a solution without the use of any imported modules? – slashdotblake Oct 07 '18 at 21:56
0

I would recommend you to use high performant counter. A counter is a container that stores elements as dictionary keys, and their counts are stored as dictionary values.

import collections a = ["blue", "green", "green", "yellow", "yellow", "yellow", "orange", "orange", "silver", "silver", "silver", "silver"] counter = collections.Counter(a) colors = counter.keys() for color in colors: print 'Color: %s, Total: %d' % (color, counter[color])

0

As requested using no imports, only thing used here was str.count and list comprehension

lista = [
    'blue', 'green', 'green', 'yellow', 'yellow', 'yellow', 'orange', 
    'orange', 'silver', 'silver', 'silver', 'silver'
]

listb = []
for i in lista:
    if i not in listb:
        listb.append(i)

for i in sorted(listb):
    print('Color: {}, Total: {}'.format(i.ljust(6), lista.count(i)))
Color: blue  , Total: 1
Color: green , Total: 2
Color: orange, Total: 2
Color: silver, Total: 4
Color: yellow, Total: 3

Honestly you don't need many tools to accomplish this, if anything I would have just used listb = set(lista) but you said no set, I threw in the .ljust(6) for fun and makes the output prettier

vash_the_stampede
  • 4,590
  • 1
  • 8
  • 20
  • Really nice example here using the count function. Appreciate the post. The second list I believe you meant to write, listb = []. Your method and Slider's second method are the basic ways I was looking to resolve this problem. I gave the edge to slider because he computed counts manually which I had wanted to do but slipped my mind. – slashdotblake Oct 08 '18 at 19:07
  • @slashdotblake yep typo! glad we were able to assist :) – vash_the_stampede Oct 08 '18 at 19:12