Convert namedtuple to dictionary

T

tripsvt

Need suggestions.

Say, I have a namedtuple like this:

{'a': brucelee(x=123, y=321), 'b': brucelee('x'=123, 'y'=321)

I need to convert it to:

{'a': {'x':123, 'y': 321},'b': {'x':123, 'y': 321}}

Follow-up question --

Which would be easier to work with if I had to later extract/manipulate the 'x', 'y' values? The format (dicts) above or a list of values like this:

{'a': ['x':123, 'y': 321],'b': ['x':123, 'y': 321]}
 
T

Tim Chase

Say, I have a namedtuple like this:

{'a': brucelee(x=123, y=321), 'b': brucelee('x'=123, 'y'=321)

I need to convert it to:

{'a': {'x':123, 'y': 321},'b': {'x':123, 'y': 321}}

While it uses the "private" member-variable "_fields", you can do
{'a': {'y': 321, 'x': 123}, 'b': {'y': 432, 'x': 234}}

which can be made a bit more readable with a helper function:
.... return dict((s, getattr(some_named_tuple, s)) for s in some_named_tuple._fields)
....{'a': {'y': 321, 'x': 123}, 'b': {'y': 432, 'x': 234}}

This would also make it easier to change/choose in the event
"_fields" ever changes.

-tkc
 
M

MRAB

Need suggestions.

Say, I have a namedtuple like this:

{'a': brucelee(x=123, y=321), 'b': brucelee('x'=123, 'y'=321)

I assume you mean:

{'a': brucelee(x=123, y=321), 'b': brucelee(x=123, y=321)}
I need to convert it to:

{'a': {'x':123, 'y': 321},'b': {'x':123, 'y': 321}}
You can get the field names using ._fields and the values by using
list(...):
[123, 321]

Zip then together and pass the result to dict:
{'x': 123, 'y': 321}

And, finally, putting that in a dict comprehension:
{'a': {'x': 123, 'y': 321}, 'b': {'x': 123, 'y': 321}}
Follow-up question --

Which would be easier to work with if I had to later extract/manipulate the 'x', 'y' values? The format (dicts) above or a list of values like this:

{'a': ['x':123, 'y': 321],'b': ['x':123, 'y': 321]}
That's not valid Python!
 
N

Ned Batchelder

Need suggestions.

Say, I have a namedtuple like this:

{'a': brucelee(x=123, y=321), 'b': brucelee('x'=123, 'y'=321)

I need to convert it to:

{'a': {'x':123, 'y': 321},'b': {'x':123, 'y': 321}}

Namedtuples have a ._asdict() method. You can convert your dictionary of
namedtuples (let's call it tupledict) like this:

dictdict = { k: nt._asdict() for k, nt in tupledict }

--Ned.
Follow-up question --

Which would be easier to work with if I had to later extract/manipulate the 'x', 'y' values? The format (dicts) above or a list of values like this:

{'a': ['x':123, 'y': 321],'b': ['x':123, 'y': 321]}
 
S

Steven D'Aprano

While it uses the "private" member-variable "_fields", you can do

It's not actually private!

namedtuple is documented as an exception to the rule that methods
starting with a single leading underscore are private. Named tuples
define three public methods and one data attribute. In order to avoid
clashing with field names, they start with a single underscore, but they
are documented as public:

_make
_asdict
_replace
_fields


http://docs.python.org/2/library/co...factory-function-for-tuples-with-named-fields
 
M

MRAB

It's not actually private!

namedtuple is documented as an exception to the rule that methods
starting with a single leading underscore are private. Named tuples
define three public methods and one data attribute. In order to avoid
clashing with field names, they start with a single underscore, but they
are documented as public:

_make
_asdict
_replace
_fields


http://docs.python.org/2/library/co...factory-function-for-tuples-with-named-fields
Wouldn't it have made more sense to have a trailing underscore instead?
 
T

Terry Reedy

Wouldn't it have made more sense to have a trailing underscore instead?

Users might use such to avoid clashes with keywords and builtins:
'print_', 'id_', 'as_', and will certainly sometimes use embedded _.
 
S

Steven D'Aprano

Need suggestions.

Say, I have a namedtuple like this:

{'a': brucelee(x=123, y=321), 'b': brucelee('x'=123, 'y'=321)


That's not a namedtuple, that's a dict containing two namedtuples.

I need to convert it to:

{'a': {'x':123, 'y': 321},'b': {'x':123, 'y': 321}}


Why bother? But if you must:

for key, value in some_dict.items():
some_dict[key] = value._asdict()

ought to work.

Follow-up question --

Which would be easier to work with if I had to later extract/manipulate
the 'x', 'y' values? The format (dicts) above or a list of values like
this:

{'a': ['x':123, 'y': 321],'b': ['x':123, 'y': 321]}

That's not legal Python.

The answer depends on what you mean by "extract/manipulate" the x and y
fields. If all you are doing is looking them up, then a namedtuple is
easiest, since that's what you've already got:

for value in some_dict.values():
print(value.x)
print(value.y)



But if you need to change those values, then a namedtuple is no good
because it is immutable. In that case, you can either create a new
namedtuple, or just use the dict-of-dicts version.



# Untested
for key, value in some_dict.items():
kind = type(value) # what sort of namedtuple is it?
new = kind(value.x+1, value.y+2)
some_dict[key] = new
 
P

Peter Otten

Need suggestions.

Say, I have a namedtuple like this:

{'a': brucelee(x=123, y=321), 'b': brucelee('x'=123, 'y'=321)

I need to convert it to:

{'a': {'x':123, 'y': 321},'b': {'x':123, 'y': 321}}

Follow-up question --

Which would be easier to work with if I had to later extract/manipulate
the 'x', 'y' values? The format (dicts) above or a list of values like
this:

{'a': ['x':123, 'y': 321],'b': ['x':123, 'y': 321]}

One more:
.... return dict(zip(n._fields, n))
....{'a': {'y': 321, 'x': 123}, 'b': {'y': 321, 'x': 123}}
 
T

Tim Chase

It's not actually private!

namedtuple is documented as an exception to the rule that methods
starting with a single leading underscore are private. Named tuples
define three public methods and one data attribute. In order to
avoid clashing with field names, they start with a single
underscore, but they are documented as public:

_make
_asdict
_replace
_fields

Well dang if "leading underscore suggests private/internal use"
convention got tossed out the window here :)

But indeed, they are in the docs, so (to the OP), use _asdict() and
make life easy.

-tkc
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,997
Messages
2,570,239
Members
46,827
Latest member
DMUK_Beginner

Latest Threads

Top