4

Using Python 3.4

I've got a way that works, but I think there might be a better way. I want to have a list with a method expand() which chooses a random element from the list, but every time that element is chosen, a counter is incremented. I tried subclassing str to be able to add attributes but it didn't work.

My main problem with what I've got is that the expression random.randint(0,len(self)-1) and using a local variable doesn't seem very Pythonic. Before I added the counter, I could just type random.choice(self)

class clauses(list):
    def __init__(self):
        self.uses = []

    def __setitem__(self,key,value):
        self.uses[key]=value
        super().__setitem__(self,key,value)

    def __delitem__(self,key):
        del(self.uses[key])
        super().__delitem__(key)

    def append(self,value):
        self.uses.append(0)
        super().append(value)

    def extend(self,sequence):
        for x in sequence:
            self.uses.append(0)
            super().append(x)

    def expand(self):

        n = random.randint(0,len(self)-1)

        self.uses[n] += 1
        return(self[n])
10
  • What will happen to the counters if a particular element is removed? Commented May 3, 2015 at 7:22
  • instead of random.randint(0, len(self) - 1) use random.randrange(0, len(self)), which has existed ever since Python 1.5.2 Commented May 3, 2015 at 7:32
  • should self.uses[key]=value be instead self.uses[key] = 0? Seems that otherwise you're setting the counter to the value in the list... Commented May 3, 2015 at 7:38
  • Note also that list supports slice indexing (i.e. the key in __setitem__ and __delitem__ could be a slice object). Commented May 3, 2015 at 7:41
  • 1
    What about also initializing a dictionary that keeps track of the counts? This would need to be updated each time an item is added to or removed from the list. Each item could be set to myDict[element] = 0 when added and myDict[element]+=1 when chosen... Commented May 5, 2015 at 0:50

1 Answer 1

1

Initializing an empty dictionary, along with your list should solve this, assuming there are no duplicate entries within the list.

When adding an element to the list, you can also add it to the dictionary by myDict[element]=0 where myDict is the initialized dictionary, and element is the item being added to the list.

Then, when the item is selected, you can simply do: myDict[element]+=1.

When dealing with an instance of duplicate entries, you could create a dictionary of dictionaries in which each key in the dictionary is a word, and the nested dictionary keys for each word are, say, index positions of the duplicate word (the values of course being the actual counts). This does add substantial complication, however, as when you remove an item from your list you will need to also update index positions. This nested data structure would like something like this though: { word1: {position1: count1}, word2: {position1: count1, position 2: count2}....}

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks @FortyLashes, I think a dictionary is the way to go. Now I've thought about it, the duplicate behaviour will be okay, as this is a counter for how many times an element of a phrase has been used. If I create a new key each time a new element is added, and just increase the counter any other time, it should work. In fact, it should work better!
@JamesWilson Please accept my answer as being the solution to your problem.

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.