Reputation: 1365
I have a list of lists containing predominantly numeric values. I need to find the highest value, determine the index of that list it contains, and sum up all values in that list.
I have this code that works fine:
results = [[213, 124, 100],
[123.7, 444.6, 111, 12],
[],
[22, 11, 100, 2],
[-1000]]
highest, row, total = -1, 0, 0
for a, b in enumerate(results):
for i in b:
if i > highest:
highest = i
row = a
total = sum(b)
The problem is that I need to make sure, that the algorithm does not break if one of the values is a string. Is there a way to ignore strings in sum, or I'd need to iterate through b as well and check for strings?
Upvotes: 0
Views: 2205
Reputation: 180441
If you want the index and the sublist with the highest single value:
results = [[213, 124, 100],
[123.7, 444.6, 111, 12],
[],
[22, 11, 100, 2],
[-1000]]
def try_mx(x):
try:
return max((i for i in x[1] if isinstance(i, (int, float))))
except ValueError:
return float("-inf")
mx_ind = max(enumerate(results), key=try_mx)
print(mx_ind)
Which will give you the index and the sublist:
(1, [123.7, 444.6, 111, 12])
In your own code every time if i > highest
is True you call sum, sum should only be called once per sublist if you found a higher value not every time you find a higher value.
You can use max again so you call sum only if the highest value is greater than the current highest, using python3 you can give max a default to catch your empty lists:
highest, row, total = float("-inf"), 0, 0
for a, b in enumerate(results):
mx = max((i for i in b if isinstance(i, (int,float))), default=float("-inf"))
if mx > highest:
highest = mx
row = a
total = sum(b)
Upvotes: 1
Reputation: 1122372
You are already iterating through b
; just check each value is not a string then. But yes, when using sum
you need to filter out values that are strings too, use a generator expression:
for a, b in enumerate(results):
for i in b:
if not isinstance(i, str) and i > highest:
highest = i
row = a
total = sum(i for i in b if not isinstance(i, str))
You could inverse the test and make sure the value is an int or float instead:
for a, b in enumerate(results):
for i in b:
if isinstance(i, (int, float)) and i > highest:
highest = i
row = a
total = sum(i for i in b if isinstance(i, (int, float)))
It'd be much better if you could ensure the lists contained only numbers up front however:
highest, row, total = 0, 0, 0
filtered_results = [[i for i in b if isinstance(i, (int, float))] for b in results]
for a, b in enumerate(filtered_results):
for i in b:
if i > highest:
highest = i
row = a
total = sum(b)
Upvotes: 1