Given the following list my_list = [ ['red', 'yellow', 'green'], ['red', 'yellow', 'green'], ['red', 'green', 'red']], I want to find the element which appears at most. I have implemented a brute-force mathod together with a new list and a dictionary to hold the values for each element but the efficiency is not satisfactory. Which would be the best way to implement this search ? I am using Python 3.  
            Asked
            
        
        
            Active
            
        
            Viewed 2,053 times
        
    1
            
            
        - 
                    1What do you mean by "brute-force"? It's not like there is a magic algorithm out there that can count elements in a list without iterating over it. – DeepSpace Jan 19 '18 at 13:46
- 
                    I used 3 for loops. Copied all different elements in a new `list` and then used one `for` loop to keep track of each item in my new list and two more nested `for` loops for the given list. – Jan 19 '18 at 13:49
3 Answers
3
            my_list = [ ['red', 'yellow', 'green'], ['red', 'yellow', 'green'], ['red', 'green', 'red']]
new_list = [k for v in my_list for k in v]
from collections import Counter
c = Counter(new_list)
print c.most_common(1)
>>> [('red', 4)]
 
    
    
        Veera Balla Deva
        
- 790
- 6
- 19
- 
                    1For sake of memory, use a generator instead of `new_list`: `print(Counter(element for sublist in my_list for element in sublist).most_common(1))` – DeepSpace Jan 19 '18 at 14:01
1
            
            
        You can flatten the nested list and apply the max function:
my_list = [ ['red', 'yellow', 'green'], ['red', 'yellow', 'green'], ['red', 'green', 'red']]
new_list = [i for x in my_list for i in x]
max_val = max(new_list, key=lambda x:new_list.count(x))
Output:
'red'
 
    
    
        Ajax1234
        
- 69,937
- 8
- 61
- 102
- 
                    `new_list` is just a waste of memory. You can just keep a dictionary in memory and count as you go. – DeepSpace Jan 19 '18 at 13:45
- 
                    @DeepSpace your solution would be more efficient, but how exactly would that save space? – Ajax1234 Jan 19 '18 at 13:46
- 
                    
- 
                    @Ajax1234 `new_list` is a waste of memory since it is an unnecessary flattened version of `my_list`. It can be turned into a generator at least. – DeepSpace Jan 19 '18 at 13:52
- 
                    `from collections import Counter ; print(Counter(element for sublist in my_list for element in sublist).most_common(1)) ; # [('red', 4)]` – DeepSpace Jan 19 '18 at 13:56
0
            
            
        You can flatten your list with itertools.chain.from_iterable, then use a collections.defaultdict to store the counts, and getting the max key is easy from there:
from collections import defaultdict
from operator import itemgetter
from itertools import chain
my_list = [['red', 'yellow', 'green'], ['red', 'yellow', 'green'], ['red', 'green', 'red']]
d = defaultdict(int)
for word in chain.from_iterable(my_list):
    d[word] += 1
print(max(d.items(), key = itemgetter(1))[0])
# red
 
    
    
        RoadRunner
        
- 25,803
- 6
- 42
- 75