I have a class containing:

        class CounterList:
            __n_comparisons__ = 0

            def __init__(self, data=None):
                if data is None:
                    self.data = []
                else:
                    self.data = data
                self.__n_accesses__ = 0

            def __getitem__(self, i):
                self.__n_accesses__ += 1
                return self.data[i]

            def __setitem__(self, i, item):
                self.__n_accesses__ += 1
                if type(item) != CounterNode:
                    raise ValueError("Only Counter objects can be placed in a CounterList")
                else:
                    self.data[i] = item

            def __delitem__(self, key):
                self.__n_accesses__ += 1
                del(self.data[key])

            def __len__(self):
                return len(self.data)

            def __repr__(self):
                return repr(self.data)

            def __contains__(self, item):
                raise TypeError("You can't use the 'in' keyword with a CounterList")

            def __eq__(self, other):
                self.__n_comparisons__ += 1
                return self.data == other

            def insert(self, index, item):
                if type(item) != CounterNode:
                    raise ValueError("Only Counter objects can be added to a CounterList")
                else:
                    self.data.insert(index, item)

            def index(self, a=None):
                raise TypeError("You can't do that with a CounterList")

            def append(self, item):
                if type(item) != CounterNode:
                    raise ValueError("Only Counter objects can be added to a CounterList")
                else:
                    self.data.append(item)

            def get_accesses(self):
                return self.__n_accesses__

            @classmethod
            def get_comparisons(cls):
                return cls.__n_comparisons__

            @classmethod
            def reset_comparisons(cls):
                cls.__n_comparisons__ = 0

and using it I need to, using a list, return a 'counterlist' containing all the strings in the original list plus the number of times the string appears in the list.

e.g.

     original_list = ["hello", "hi", "hi"]
     CounterList = ["hello", 1, "hi", 2]

I am a little lost, but have made a start on a while loop that will check the original list against the new list and if the string is not there, then will add it to the new list, and increase a counter by one, then it will delete the first item in the original list until that list is empty before finally displaying the result.

I am fairly lost however, and any guidence will be much appreciated, as I am sure there must be an easier way to do this.

Thank you

    from classes_1 import CounterList

    def word_counter_seq(words_list):
        counter = 0
        new_list = []
        while words_list != False:
            if words_list[0].__eq__(new_list):
                counter += 1
                words_list[0].append[new_list]
                words_list[0].__delitem__()
            else:
                counter+=1
                words_list[0].__delitem__()
        print (counter)
        print (new_list)


    a_list = ["hello", "hi", "hi"]
    (word_counter_seq(a_list)) 

using a list, return a 'counterlist' containing all the strings in the original list plus the number of times the string appears in the list

You want a list of lists. While the list in your post can work
CounterList = ["hello", 1, "hi", 2]
a list of list is easier to understand. In your list you would have to check the new word against every other element in CounterList (skip the number), which can be done but is more confusing.

def test_for_word(word, counter_list):
    for ctr in range(len(counter_list)):
        sub_list = counter_list[ctr]
        print "     checking sub_list (word, number)", sub_list
        if word == sub_list[0]:
            sub_list[1] += 1
            return counter_list
    counter_list.append([word, 1])
    return counter_list

original_list = ["hello", "hi", "hi"]
counter_list = []
for word_1 in original_list:
    counter_list = test_for_word(word_1, counter_list)
    print word_1, counter_list

Edited 2 Years Ago by woooee

There is also collections.Counter.

from collections import Counter
wordcount = Counter(['this', 'this', 'that', 'that', 'that', 'and'])
print(repr(wordcount))
# Reveals:
# {'this': 3, 'that': 2, 'and': 1}

Not only is it easy, but I'm pretty sure it performs better (coded in C).
If you really wanted it in list format you could do this to it:

wordcountlist = []
for word, count in wordcount.items():
    wordcountlist.extend((word, count))

Or you could combine the two:

words = ['this', 'this', 'that', 'that', 'that', 'and']
wordcountlist = []
for word, count in Counter(words).items():
    wordcountlist.extend((word, count))

The order may be off, because of the Counter converting to dict. Honestly, if you are going to be retrieving the counts in the future, a dict may be better anyway. Retrieving the count would just be: wordcount['this'] or wordcount[myword]. ..instead of having to construct your own for-loop to retrieve/parse the counts.

Edited 2 Years Ago by chriswelborn: formatting code error.

If you really wanted it in list format you could do this to it:

Yes i agree if that's really what BingityBongity want,
but a plain list with no connetion between vaules seems not right.
Just use dict.items() then key and value from dict are together in tuple.

>>> d = {'this': 3, 'that': 2, 'and': 1}
>>> d.items()
[('this', 3), ('and', 1), ('that', 2)]

Just use dict from collections.Counter is the best way.

Edited 2 Years Ago by snippsat

This certainly sounds like homework, i.e. lists must be used. Another way is to sort the list first and then count.

original_list = ["hello", "hi", "hi", "bye", "hi", "bye"]
original_list.sort()
counter_list = []
ctr = 0
previous = original_list[0]
for word in original_list:
    if word != previous:
        counter_list.append([previous, ctr])
        ctr = 0
        previous = word
    ctr += 1

counter_list.append([word, ctr])
print counter_list

If libraries aren't allowed, you could make your own Counter.

words = ['this', 'this', 'that', 'that', 'that', 'and']
wordcount = {}
for word in words:
    existing = wordcount.get(word, 0)
    wordcount[word] = existing + 1

wordcountlist = []
for word, count in wordcount.items():
    wordcountlist.extend((word, count))

print(repr(wordcountlist))
# ['this', 2, 'that', 3, 'and', 1]

Of course, there are libraries that would simplify this too..

from collections import defaultdict
wordcount = defaultdict(int)
for word in words:
    wordcount[word] += 1

Anyway, I think there are some good answers here no matter what the constraints are on the problem. Plenty to choose from. :)

One more possibility ...

from collections import Counter

original_list = ["hello", "hi", "hi", "bye", "hi", "bye"]

# most_common() gives a list of all (word, freq) tuples sorted by count
wordcount = Counter(original_list).most_common()

print(wordcount)

''' result ...
[('hi', 3), ('bye', 2), ('hello', 1)]
'''
This question has already been answered. Start a new discussion instead.