#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2012
    Posts
    1
    Rep Power
    0

    How to append the number of item frequencies in a list in Python 3.2?


    Greetings, I'm new to the forums and I'm also new to programming.

    The question I want to ask is how do you count the frequency of items in a list
    so they add up in order with "PARTY_INDICES"? in my case that is.

    This is a docstring of what I need to do:
    Code:
    ''' (list of str) -> tuple of (str, list of int) 
    votes is a list of single-candidate ballots for a single riding. 
    Based on votes, return a tuple where the first element is the name of the party 
    winning the seat and the second is a list with the total votes for each party in 
    the order specified in PARTY_INDICES. 
    
    >>> voting_plurality(['GREEN', 'GREEN', 'NDP', 'GREEN', 'CPC']) 
    ('GREEN', [1, 3, 0, 1])
    '''
    Since PARTY_INDICES = [NDP_INDEX, GREEN_INDEX, LIBERAL_INDEX, CPC_INDEX]
    This produces a tuple of the winning party (In this case 'GREEN') and the list of
    frequencies, where [1, 3, 0, 1]


    These are list of global variables, lists and dictionaries:
    Code:
    #  The indices where each party's data appears in a 4-element list.
    NDP_INDEX = 0
    GREEN_INDEX = 1
    LIBERAL_INDEX = 2
    CPC_INDEX = 3
    
    # A list of the indices where each party's data appears in a 4-element list.
    PARTY_INDICES = [NDP_INDEX, GREEN_INDEX, LIBERAL_INDEX, CPC_INDEX]
    
    # A dict where each key is a party name and each value is that party's index.
    NAME_TO_INDEX = {
      'NDP': NDP_INDEX,
      'GREEN': GREEN_INDEX,
      'LIBERAL': LIBERAL_INDEX,
      'CPC': CPC_INDEX
    }
    
    # A dict where each key is a party's index and each value is that party's name.
    INDEX_TO_NAME = {
      NDP_INDEX: 'NDP',
      GREEN_INDEX: 'GREEN',
      LIBERAL_INDEX: 'LIBERAL',
      CPC_INDEX: 'CPC'
    }
    This is my work:

    Code:
    def voting_plurality(votes):
        my_list = []
        my_dct = {}
        counter = 0
        for ballot in votes:
            if (ballot in my_dct):
                my_dct[ballot] += 1
            else:
                my_dct[ballot] = 1
    
        if (my_dct):
            my_dct = my_dct.values()
            new_list = list(my_dct)
                      
        return (max(set(votes), key = votes.count), new_list)
    it returns
    Code:
    >>> voting_plurality(['GREEN', 'GREEN', 'NDP', 'GREEN', 'CPC'])
    ('GREEN', [1, 1, 3])
    But I want it to to also include the party with no votes and is in order with PARTY_INDICES [1, 3, 0, 1]


    My code may look like nonsense, but I'm really stuck and confused

    and also I cannot IMPORT anything.
  2. #2
  3. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,900
    Rep Power
    481
    Write import instead of IMPORT.
    [code]Code tags[/code] are essential for python code and Makefiles!
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2012
    Posts
    39
    Rep Power
    3
    You have massively overcomplicated the code so lets go back to the requirement. At first it would seem a dictionary is the way to go and it is if you want to optimise you code. However you can do it another way.

    You need to record the votes for each given party so lets start with a list of the parties in the order you want them to appear. This can be done follows:
    PARTIES = [ 'NDP' , 'GREEN' , 'LIBERAL' , 'CPC' ]

    In general, given any list you can count the occurrances of a value with the count method. So to find the number of times the string NDP appears in the list votes you just need:
    votes.count('NDP')

    You have used max to get the party with the most votes which is a clever far beyond the rest of the code. This makes me think it was copied. By using the optional key value, it is giving the item a value of the number of times it appears in the list and picking the highest value.

    If I put the value in brackets it might explain better. Using you example it will give the votes list the following values:
    ['GREEN' (3), 'GREEN' (3), 'NDP' (1), 'GREEN' (3), 'CPC' (1)]

    It will then pick one (the first occurrance I think) with the highest value, in this case GREEN. Note that this has called count on the list 5 times in just this small example so it is very inefficent for large lists. It will also fail in some circumstances which I'll come back to later.

    If you are going to do this, you might as use count to get the number of votes for each party. As we have a list of the parties this can be done with the map function as follows:
    map(votes.count,PARTIES)

    Python 3 users will have to use list to convert this to a list but thats all you need.

    This gives you a working function in just a couple of lines:
    Code:
    def voting_plurality (votes):
        PARTIES = [ 'NDP' , 'GREEN' , 'LIBERAL' , 'CPC' ]
        return ( max(votes,key=votes.count) ,
            list(map(votes.count,PARTIES)) )
    Not that the above would be something a new coder would produce so lets look at this from a beginners point of view.

    You can loop through the votes list using a for loop as you have done. Rather than create a new dictionary entry for each different vote we are only interested in counting the parties in our PARTIES list. Any other value is spolit.

    If you prepopulate the dictionary with all the parties having no votes you are guarenteed to record the party even if it achieves no votes. We could do this as follows but I will use the PARTIES list in the final code:
    my_dct = { 'NDP':0 , 'GREEN':0 , 'LIBERAL':0 , 'CPC':0 }

    Now we have all the parties votes in a dictionary. We can just loop through the dictionary recording the party with the highest votes and building up the list.

    This gives:

    Code:
    def voting_plurality (votes):
        PARTIES = [ 'NDP' , 'GREEN' , 'LIBERAL' , 'CPC' ]
    
        # create a dictionary for all the parties with no votes
        my_dct = dict()
        for party in PARTIES:
            my_dct[party] = 0
    
        # loop through the votes list and record the votes cast in the dictionary
        spoilt = 0
        for ballot in votes:
            if ballot in PARTIES:
                my_dct[ballot] += 1
            else: # not a valid party
                spoilt += 1
    
        # find the party with the highest number of votes
        # and create a list of the votes in order
        winner = ""
        max = 0
        votes_in_order = list()
        for party in PARTIES:
            if my_dct[party] > max:
                winner = party
                max = my_dct[party]
            votes_in_order.append(my_dct[party])
    
        return ( winner , votes_in_order )
    This is probably closer to the code expected and fixes the problems you mentioned.

    Now to the problem you missed. What happens if two or more parties tie? For example if the votes cast are ['GREEN', 'GREEN', 'NDP', 'NDP', 'CPC', 'NDP', 'CPC', 'CPC'] it will currently show NDP as the winner even though it will show they tied with CPC on 3 votes each. I'll leave you to fix this as I think I've done enough.
    Last edited by Quackajack; November 22nd, 2012 at 10:02 AM. Reason: variable spelling error
  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2012
    Posts
    39
    Rep Power
    3

    Taking it to the next level


    At the risk of confusing you, the one advantage the second method with its single iteration of the passed in votes is you are not limited to lists.

    Logically the votes are likely to be stored in a text file (which I'll call votes.txt) where each vote is on a seperate line. We can't pass this straight to our function as it will include the newline at the end.

    Instead we can use a generator to strip out the newline as follows:
    Code:
    with open("votes.txt") as f:
        mygenerator = (line.strip() for line in f)
        result = voting_plurality(mygenerator)
  8. #5
  9. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,900
    Rep Power
    481
    Quackajack, you cheated! At least I'm pretty sure you did. You wrote
    PARTIES = [ 'NDP' , 'GREEN' , 'LIBERAL' , 'CPC' ]
    by hand, that is you figured it out with your brain this one case rather than writing an algorithm to use the given information.

    Also, to Softie's instructor, the two dictionaries a_to_b and b_to_a don't conflict when merged into a single dictionary because the key and value data types differ.
    Code:
    NDP_INDEX = 0
    GREEN_INDEX = 1
    LIBERAL_INDEX = 2
    CPC_INDEX = 3
    
    PARTY_INDICES = [NDP_INDEX, GREEN_INDEX, LIBERAL_INDEX, CPC_INDEX]
    
    THIS_TO_THAT = {
      'NDP': NDP_INDEX,
      'GREEN': GREEN_INDEX,
      'LIBERAL': LIBERAL_INDEX,
      'CPC': CPC_INDEX,
      NDP_INDEX: 'NDP',
      GREEN_INDEX: 'GREEN',
      LIBERAL_INDEX: 'LIBERAL',
      CPC_INDEX: 'CPC'
    }
    
    def voting_plurality(votes):
        '''
            (list of str) -> tuple of (str, list of int)
            votes is a list of single-candidate ballots for a single riding.
            Based on votes, return a tuple where the first element is the name of the party
            winning the seat and the second is a list with the total votes for each party in
            the order specified in PARTY_INDICES.
    
            >>> voting_plurality(['GREEN', 'GREEN', 'NDP', 'GREEN', 'CPC'])
            ('GREEN', [1, 3, 0, 1])
        '''
        return(max(set(votes),key=votes.count),[votes.count(THIS_TO_THAT[idx]) for idx in PARTY_INDICES])
    Last edited by b49P23TIvg; November 22nd, 2012 at 08:43 PM.
    [code]Code tags[/code] are essential for python code and Makefiles!

IMN logo majestic logo threadwatch logo seochat tools logo