python. counting in nested list the max of 3rd element of each element according to the second element

Viewed 126

I know the title is bit hard to understand. Sorry for that, let me explain. for example: we have a nested list consist of 4 lists each with 3 elements, the first two are strings(not char) and the third one is an int:

LLList = [ ["A", "B", 30], ["C", "B", 30], ["D", "B", 20], ["D", "L", 60] ]

I want to count the number or return all indexes of elements in the "LLList" (elements in the "LLList" are the triple-element lists like ["A", "B", 30]) where the third element is greatest where the second element is "B".

A naive way would be to find all elements whose second elements is "B" and put it in a list. in this case would be:

TempList = []

for w in LLList
    if w[1] == "B"
    TempList.append(w)

The result would be:

TempList = [ ["A", "B", 30], ["C", "B", 30], ["D", "B", 20] ]

Then find the max value among the 3rd elements in TempList in this case would be 30

MaxB = max(TempList, key = lambda x:x[2])[2] # MaxB = 30

And count the occurrence of MaxB in the 3rd column of TempList

[p[2] for p in TempList].count(MaxB)

In this case would be 2

This is a overly naive method, too much to code, need too much RAM and time to complete, I know it, but I cannot think of anything better than this. I know there must be an elegant and effective way to solve this problem, please help me, thank you very much!

3 Answers
dict_ans = {}
for sub in LLList:
    if sub[1] == 'B':
        dict_ans[sub[2]] = dict_ans.get(sub[2], 0) + 1

print (dict_ans)
#{30: 2, 20: 1}

print (max(value for key, value in dict_ans.items())
#2

Simple way using numpy.amax and list comprehension.

This will find your values:

import numpy as np    
maxB = [x for x in LLList if x[1]=='B' and x[2] == np.amax([x[2] for x in LLList if x[1]=='B'])]

It finds all the values that have B in x[1], and x[2] is equal to the maximum of the values with the B.

After that you just need to find the indexes:

[LLList.index(x) for x in maxB]

You can also use collections.Counter:

from collections import Counter

LLList = [ ["A", "B", 30], ["C", "B", 30], ["D", "B", 20], ["D", "L", 60] ]

a = Counter([i[2] for i in LLList if i[1]=="B"])

print (a.most_common(2))

#[(30, 2), (20, 1)]

print (sorted(a.items(),key=lambda x: x[0],reverse=True)) #or get highest value

#[(30, 2), (20, 1)]
Related