3
\$\begingroup\$

I have a dictionary structured as {a_1: [((b_11,c_11),d_11), ((b_12, c_12), d_12), ...], a_2: [...], ...}.

I want to extract the maximum abs(c) among all the possible c values. Currently I'm doing this throught two for loops. One for each a, and other for each of set {b,c,d}.

elements = {
 0: [((0, -4), 1)], 
 1: [((1, -5), 1), ((0, -4), 1)],
 2: [((2, -3), 1)],
 3: [((3, -2), 1), ((0, -5), 1)],
 }
max_c = 0
for a in list(elements):
 for (b, c), d in elements[a]:
 max_c = max(max_c, abs(c))

Is there any way to do this without the for loops? and if it is, is it pythonic? or I should keep this way because it's more understandable?

Thanks in advance.

asked Oct 17, 2018 at 8:32
\$\endgroup\$

2 Answers 2

9
\$\begingroup\$
  1. When you are looping over the keys a and values elements[a] of a dictionary, use the items method to loop over both at the same time:

    for a, value in elements.items():
     for (b, c), d in value:
    

    (If I knew what these values represented, I would pick a better name than value.)

  2. The code here doesn't use the keys, it only uses the values. So use the values method instead:

    for value in elements.values():
     for (b, c), d in value:
    
  3. The code doesn't use b or d either. It is conventional to use the name _ for unused variables:

    for (_, c), _ in value:
    
  4. A double iteration over some lists and then over the elements of those lists can be combined into a single iteration using itertools.chain.from_iterable:

    from itertools import chain
    for (_, c), _ in chain.from_iterable(elements.values()):
    
  5. The repeated calls to max can become a single call taking a generator expression:

    values = chain.from_iterable(elements.values())
    max_abs_c = max(abs(c) for (_, c), _ in values)
    
  6. It's common to worry whether code is "Pythonic" but it is better to think in terms of general principles (clarity, simplicity, maintainability, testability, usability, efficiency, etc.) that apply to code in any language.

answered Oct 17, 2018 at 11:12
\$\endgroup\$
0
6
\$\begingroup\$

If you were to extract all abs(c) into a list, you could use max over that list.

Fortunately, this is easy using your loops and a list-comprehension:

Cs = [
 abs(value)
 for collection in elements.values()
 for (_, value), _ in collection
]
max_c = max(Cs)

Note the use of elements.values() instead of extracting the values manually (elements[a]) and the use of _ as a throwaway variable.

Now max works on any iterable, meaning we don't even have to build a temporary list and can feed it a generator-expression:

max_c = max(
 abs(value)
 for collection in elements.values()
 for (_, value), _ in collection
)
answered Oct 17, 2018 at 11:11
\$\endgroup\$
0

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.