1

I have a dict which looks something like

A = {
    'test1':{'q0':[0.123,0.234],'phi0':[0.124,0.4325],'m':[9.42,0.3413]},
    'test2':{'q0':[0.343,0.353],'phi0':[0.2341,0.235]},
    'test3':{'q0':[0.343,0.353],'phi0':[0.2341,0.235],'m':[0.325,0.325],'z0':[0.234,0.314]}
    }

I want to print each individual dictionary:

'test1':                 q0=0.123(0.234) phi0=0.123(0.4325) m=9.42(0.3413)
'test2':                 q0=0.343(0.353) phi0=0.2341(0.235)
'test3': z0=0.234(0.314) q0=0.343(0.353) phi0=0.2341(0.235) m=0.325(0.325)

How to do so in Python 3 using thestring.format()? Since each sub-dictionary has variable number of 'parameters', I am not sure how to accomplish it using some list/dictionary comprehension. Also, if I want to leave some space if that parameter is missing like what is shown, how do I do it? Each dictionary has at most five different parameters (q0,phi0,m,c,z0). I juts print it to the terminal so I don't need something very fancy, but I hope it can be more readible.

2
  • You can consider writing a function which takes a key, value of dictionary as input and returns the output in the required format and the print it. Commented Jan 3, 2018 at 7:58
  • Part of what you want is sorting the sub-dictionary keys into the order: ['z0','q0','phi0','m'] either by custom sort order or reverse-alphanumeric. Are you ok with writing that code separately, or do you want to stick it in the formatting code? Commented Sep 10, 2018 at 3:35

6 Answers 6

5

Note that dictionaries are unordered data structures, hence you can't expect any order in printing the items unless you use their ordered equivalent collections.OrderedDict(). Nevertheless, you can use a generator expression within str.join() method :

In [4]: for key, value in A.items():
    print(','.join(("{}: {}={}({})".format(key, t1,t2,t3) for t1, (t2, t3) in value.items())))
   ...:     
test1: q0=0.123(0.234),test1: phi0=0.124(0.4325),test1: m=9.42(0.3413)
test3: q0=0.343(0.353),test3: phi0=0.2341(0.235),test3: m=0.325(0.325),test3: z0=0.234(0.314)
test2: q0=0.343(0.353),test2: phi0=0.2341(0.235)

Also note that since we're doing the following inline unpacking it may raise a ValueError if number of the items in lists is more/less than two.

for t1, (t2, t3) in value.items()

Therefore, make sure that the number of unpacking variables match with the number of items in list.

Sign up to request clarification or add additional context in comments.

1 Comment

Except the OP's output sorts the sub-dictionary keys into (reverse-alphanumeric?) order: ['z0','q0','phi0','m']. And missing tuples appear as blank-padded fields.
1

As both your tests and parameters are in dictionaries, you could first sort them to ensure a consistent ordering. Simple sorting may not work though as if you had test13, by default in would appear after test1. You could use the Python library natsort to help with this.

As each set of parameters could have missing values, a quick search could be used to create a list of all of the cols that are needed. You could then reserve space when printing for rows with missing values:

from natsort import natsorted

A = {
    'test1':{'q0':[0.123,0.234],'phi0':[0.124,0.4325],'m':[9.42,0.3413]},
    'test2':{'q0':[0.343,0.353],'phi0':[0.2341,0.235]},
    'test3':{'q0':[0.343,0.353],'phi0':[0.2341,0.235],'m':[0.325,0.325],'z0':[0.234,0.314]},
    'test13':{'q0':[0.343,0.353],'z0':[0.234,0.314]}
    }

sorted_tests = natsorted(A.items())     # Ensure test13 is numerical sorted correctly
# Create a list of all required cols
cols = set()

for test, params in sorted_tests:
    cols.update(params.keys())

cols = sorted(cols)    

for test, params in sorted_tests:
    row = [(col, params.get(col, [])) for col in cols]
    cells = []
    for p, values in row:
        if values:
            cells.append('{:20}'.format('{}={}({})'.format(p, values[0], values[1])))
        else:
            cells.append('{:20}'.format(''))

    print("{:6} : {}".format('{}'.format(test), ''.join(cells)))

This would give you the following output:

test1  : m=9.42(0.3413)      phi0=0.124(0.4325)  q0=0.123(0.234)                         
test2  :                     phi0=0.2341(0.235)  q0=0.343(0.353)                         
test3  : m=0.325(0.325)      phi0=0.2341(0.235)  q0=0.343(0.353)     z0=0.234(0.314)     
test13 :                                         q0=0.343(0.353)     z0=0.234(0.314)

Comments

1

Check if 'z0' is in the keys of the sub-dictionaries, and to those items, apply a slightly different string operation than the ones that don't have that key. Looks a little dirty but produces your output exactly:

for k,v in A.items():
    if 'z0' in v:
        print (k,":","{}={}({})".format('z0',v['z0'][0],v['z0'][1]), " ".join("{}={}({})".format(e,t[0],t[1]) for e,t in v.items() if 'z0' not in e))
    else:
        print (k,":                "," ".join("{}={}({})".format(e,t[0],t[1]) for e,t in v.items()))

Result:

test1 :                 q0=0.123(0.234) phi0=0.124(0.4325) m=9.42(0.3413)
test2 :                 q0=0.343(0.353) phi0=0.2341(0.235)
test3 : z0=0.234(0.314) q0=0.343(0.353) phi0=0.2341(0.235) m=0.325(0.325)

Note: If you really need those single quotes around the tests, i.e. 'test1' instead of test1, you can add "'" to the left and right of k in the two print statements of mine: print ("'",k,"'",...

Comments

1

use a nested loop:

for m,x in A.items():
    for y,z in x.items():
        print(m,'{0}='.format(y), z[0],'({0})'.format(z[1]))

Comments

0

Try following code based on for loop which produces a sorted output:

outlist = []
for a in A:
    outstr = a+":"
    for aa in ('z0', 'q0','phi0','m','c'):
        if aa in A[a]:
            outstr += aa+"="+str(A[a][aa][0])+"("+str(A[a][aa][1])+") "
        else:
            outstr += "                "
    outlist.append(outstr)

for i in sorted(outlist):
    print(i)

Output:

test1:                q0=0.123(0.234) phi0=0.124(0.4325) m=9.42(0.3413)                 
test2:                q0=0.343(0.353) phi0=0.2341(0.235)                                 
test3:z0=0.234(0.314) q0=0.343(0.353) phi0=0.2341(0.235) m=0.325(0.325)          

Comments

0

Try this:-

A = {
    'test1':{'q0':[0.123,0.234],'phi0':[0.124,0.4325],'m':[9.42,0.3413]},
    'test2':{'q0':[0.343,0.353],'phi0':[0.2341,0.235]},
    'test3':{'q0':[0.343,0.353],'phi0':[0.2341,0.235],'m':[0.325,0.325],'z0':[0.234,0.314]}
    }
for i,j in A.items():
    print i+':',
    for x,y in j.items():
        print "{}= {}({})".format(x,y[0],y[1]),
    print 
#output is same as expected

Comments

Your Answer

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.