1

Problem Description

I am firstly I am having a list of values like:

(1,2,3,1,3,2,2,2,1)

What I want to achieve is :

  1. Find the most common one (working).
  2. Delete it from the list (working).
  3. Repeat the same thing for the remaining values in the list.

For instance

Taking this Tuple:

(1,2,3,1,3,2,2,2,1) 

Store that 2 is the most common int, then

(1,3,3,1,1,)

Store that 1 is the second most common int, then

(3,3) 

Store that 2 is the third most common int, then


My source Code

NOTE lets say that self.final_votes would be (1,2,3,1,3,2,2,2,1)

def erase_common(self):
        possitions = []
        counter = 0
        common = self.final_votes[0] 
      
        
        for i in self.final_votes:
            cand_freq = self.final_votes.count(i) 
            if(cand_freq> counter): 
                counter = cand_freq
                common = i
        
         possitions.append(common)
         while common in self.final_votes:
         self.final_votes.remove(common)    

this is the whole code

class voting_system:
    def __init__(self):
        #self.tutor_group = self.get_tutor_group()
        self.stud_num = self.get_stud_num()
        self.cand_num = self.get_cand_num()
        self.cand_name = self.get_cand_name()
        self.final_votes = self.ind_votes()
        self.erase_common()
        
#     def get_tutor_group(self):
#         tutor_groups = ("7A","7B","7C","7D","7E","7F","8A","8B","8C","8D","8E","8F","9A","9B","9C","9D","9E","9E",
#                     "9F","10A","10B","10C","10D","10E","10F","11A","11B","11C","11D","11E","11F")
# 
#         flag = True
#         while flag == True:
#             try:
#                 self.tutor_group = input("please enter the tutor group: ")
#                 if self.tutor_group not in tutor_groups:
#                     raise ValueError("Tutor group entred doesn't exist")
#             except ValueError as error:
#                 print(error)
#                 flag = True
#                     
#             else:
#                 flag = False
        
#        return self.tutor_group
        
    def get_stud_num(self):
#         flag = True
#         while flag == True:
#             try:
#                 self.stud_num = int(input("Please enter number of students: "))
#                 if self.stud_num<0 or self.stud_num>35:
#                     raise ValueError("NUMBER OF STUDENTS INVALID")
#             except ValueError as error:
#                 print(error)
#                 flag = True
#                 
#             else:
#                 flag = False
        self.stud_num = 7
        return self.stud_num
        
            
    def get_cand_num(self):
#         flag = True
#         while flag == True:
#             try:
#                 self.cand_num = int(input("Please enter number of candidates: "))
#                 if self.cand_num>4:
#                     raise ValueError("NUMBER OF CANDIDATES INVALID")
#             except ValueError as error:
#                 print(error)
#                 flag = True
#                 
#             else:
#                 flag = False
        self.cand_num = 3
        return self.cand_num
        
    
    def get_cand_name(self):
        self.cand_name = []
        for i in range(self.cand_num):
            candidate = input("Enter candidate name: ")
            self.cand_name.append(candidate)
        return self.cand_name
    
    def print_cands(self):
        for i in range(len(self.cand_name)):
            print(i+1, " : ", self.cand_name[i])
            
            
    def ind_votes(self):
        self.final_votes = []
        self.print_cands()
        abs_vote = 0
        
        flag = True
        while flag == True:
            try:
                for i in range(self.stud_num): 
                    vote = input("To vote type 'V' and the candidates number, to abstent type 'A': ")
                    if vote.isalpha() == True:
                        abs_vote +=1
                    else:
                        self.final_votes.append(vote[1])
            
                    if vote[1] > str(self.cand_num):
                        raise ValueError("VOTED CANDIDATE NONEXISTENT")
            except ValueError as error:
                print(error)
                flag = True
            else:
                flag = False
               
                
        return self.final_votes
        return abs_vote

    def erase_common(self):
        possitions = []
        counter = 0
        common = self.final_votes[0] 
      
        
        for i in self.final_votes:
            cand_freq = self.final_votes.count(i) 
            if(cand_freq> counter): 
                counter = cand_freq
                common = i
        
         possitions.append(common)
         while common in self.final_votes:
         self.final_votes.remove(common)            
        
        
                    
run = voting_system()

any suggestions would be appreciated:)

fdermishin
  • 3,519
  • 3
  • 24
  • 45
Elloder
  • 29
  • 5
  • Your post code is incomplete - it seems that you have written a `class` - guessing by `self.final_votes`? Can you post complete code? And what's the `ending condition` for the repeated checking - eg. until the last number is `n` count? – Daniel Hao Jan 06 '21 at 14:07
  • the fucntion should stop once there are no more elements in the list, I'll post the code :). – Elloder Jan 06 '21 at 14:25
  • If that's the case - what's the goal of this program then? Just an exercise? `No more elements in the list` == `empty list`? Miss the point here... – Daniel Hao Jan 06 '21 at 14:28
  • It is a exam asignment, its basicallz responsible for deciding the winners of a class vote, this part finds the largest amount of votes with the candidate's name, erases it, does it again for the others – Elloder Jan 06 '21 at 14:29
  • and because the amount of candidates is variable, I cant hard code it – Elloder Jan 06 '21 at 14:32
  • What if the final list is '[1, 3]' a 'tie'? – Daniel Hao Jan 06 '21 at 14:47
  • yea I haven't done that feature yet, I firstly wanted to have this functioning and then focus on the tie feature – Elloder Jan 06 '21 at 14:56
  • @Elloder may you add or explain what is the **expected output** and what you get now instead? And what is wrong in more specific with your code? Or you want to see a better implementation of it? – Federico Baù Jan 06 '21 at 15:53
  • Okay so bassically the smaller portion of the code is supposed to take the list then it counts what candidate number is the most common, eg candidate number 1, it saves that candidate number 1 had the most votes and erases his votes from the list, this is the part that works. – Elloder Jan 06 '21 at 16:14
  • What is left is a list without the votes from candidate 1, eg before erasion it looked like 1,1,2,3,2,3,1,3,2,1,1,2 after erasion it looks like 2,3,2,3,2,2.Now what I need, is for the same thing to happen again, but to the second most commonly voted candidate, at the end there should be a array, with their positions, for example candidate @ had most votes - he is first, candidate 3 had second most votes so he is second and so on. – Elloder Jan 06 '21 at 16:17
  • basically i need it to spit out their order, like [1,2,3] or [3,1,2] ..., the problem is that I cant simply have 3 separate blocks to do this, because the number of candidates is from 1 to 4, so I NEED SOME SORT OF UPDATING LOOP – Elloder Jan 06 '21 at 16:19
  • @Elloder makes sense and should be pretty easy to do, more easy to do than explain it. If no one answer before I would give it a go but make take me sometimes later as Im' currently not on. – Federico Baù Jan 06 '21 at 16:30
  • Ok thanks Federico, I can probably imagine that solution is pretty simple but my brain is a bit overcooked, I'll try a bit :) – Elloder Jan 06 '21 at 16:38
  • @Elloder I've posted one solution, does this answer your question? – Federico Baù Jan 06 '21 at 18:26
  • Hi federico, thanks a bunch I actually came up with my own solution, but yours is much more elegant so thanks:). Can you just explain what is going on? BTW huge appreciation for your time :) have an awesome day – Elloder Jan 06 '21 at 19:04
  • @Elloder I'm glad it helped. Basically Groupby and Counter are both algorithms and function that are within the Python Standard Library. I added the link where you can found documentation and inplementation of it, explaint it is bit difficult. They are highly efficient function. – Federico Baù Jan 06 '21 at 19:12
  • @Elloder if my answer helped you and solved the problem I suggest you to mark it as accepted so it can be removed from the queue, thanks – Federico Baù Jan 06 '21 at 19:13

1 Answers1

0

Easier and probably the best:

User Python Counter from Collection.

from collections import Counter


final_votes = [1, 2, 3, 1, 3, 2, 2, 2, 1]

def erase_common(votes):
    count_votes = Counter(votes)
    return count_votes.most_common()

print(erase_common(final_votes)) # [(2, 4), (1, 3), (3, 2)]
votes = erase_common(final_votes)
for idx, votes in enumerate(votes):
    print(f'{idx+1}) Vote {votes[0]} Total = {votes[1]}')

OUTPUT

1) Vote 2 Total = 4
2) Vote 1 Total = 3
3) Vote 3 Total = 2

Using groupby

@AlexMartelli has a really good answer regarding find most common element on list --> Find the most common element in a list

So you can implement this by doing this:

from itertools import groupby


final_votes = [1, 2, 3, 1, 3, 2, 2, 2, 1]

def most_common_oneliner(L):
    grupped = groupby(sorted(L))
    result = {group: len([*scores]) for group, scores in grupped}
    final_sorted_votes = []
    while result:
        max = [(0, 0)]
        for score, res in result.items():
            if max[0][1] < res:
                max[0] = (score, res)
        del result[max[0][0]]
        final_sorted_votes += max

    return final_sorted_votes


result = most_common_oneliner(final_votes)

for idx, votes in enumerate(result):
    print(f'{idx+1}) Vote {votes[0]} Total = {votes[1]}')

Documentation

Federico Baù
  • 6,013
  • 5
  • 30
  • 38