I've got a problem that I can't seem to get my head around and hoped
somebody might help me out a bit:
I've got a dictionary, A, that is arbitarily large and may contains
ints, None and more dictionaries which themselves may contain ints,
None and more dictionaries. Each of the sub-dictionaries is also
arbitrarily large. When pretty printing A, in the context I'm using A
for, it's rather helpful to remove all key:value pairs where value is
None. So I'd like to be able to define a function dict_sweep to recurse
through A and del all the keys with None as a value.
I feel like the solution is right on the tip of my tounge, so to speak,
but I just can't quite get it. Anyway, here's the best I've come up
with:
def dict_sweep(dictionary, key_value):
"""Sweep through dictionary, deleting any key:value where
value is None.
"""
# Find key at position key_value.
key = dictionary.keys()[key_value]
# If the key value is a dictionary we want to move into it.
# Therefore we call rec_rem on dictionary[key] with a
# key_value of 0
if type(dictionary[key]) is type({}):
dict_sweep(dictionary[key], 0)
# If the value isn't a dictionary we care only that it's not None.
# If it is None we nuke it and call rec_rem on the current
# dictionary with key_value incrimented by one.
elif dictionary[key] is None:
del dictionary[key]
dict_sweep(dictionary, key_value+1)
# If the value isn't a dictionary and the value isn't None then
# we still want to walk through to the next value in the
# dictionary, so call rec_rem with key_value+1
else:
dict_sweep(dictionary, key_value+1)
Assuming dict_sweep worked perfectly it would take input like this:
A_in = {1: {2: 2, 3: {1: None, 2: 2}}, 2: 2, 3: None}
B_in = {1: {1: {1: None, 2: {1: None}}, 2: 2, 3: None}
and output this:
A_out = {1: {2: 2, 3: {2: 2}}, 2: 2}
B_out = {2:2}
This dict_sweep above obviously doesn't work and I'm rather afraid of
hitting python's recursion limit. Does anyone see a way to modify
dict_sweep in it's current state to perform dictionary sweeps like
this? What about a non-recursive implementation of dict_sweep? 8 13034
My first try, not much tested:
def clean(d):
for key,val in d.items():
if isinstance(val, dict):
val = clean(val)
if not val:
del d[key]
return d
a = {1: {2: 2, 3: {1: None, 2: 2}}, 2: 2, 3: None}
print clean(a) # Out: {1: {2: 2, 3: {2: 2}}, 2: 2}
b = {1: {1: {1: None, 2: {1: None}}}, 2: 2, 3: None}
print clean(b) # Out: {2: 2}
Recursivity overflow problem: you can increase the recursivity limit,
of if you think you need it after some tests on your real data, then
you can use a stack (a python list, using append and pop methods) to
simulate recursivity. You probably don't have 300+ levels of nesting.
Bye,
bearophile
Better:
def clean(d):
for key,val in d.items():
if isinstance(val, dict):
val = clean(val)
if val is None or val == {}:
del d[key]
return d
a = {1: {2: 2, 3: {1: None, 2: 2}}, 2: 2, 3: None}
print clean(a) # Out: {1: {2: 2, 3: {2: 2}}, 2: 2}
b = {1: {1: {1: None, 2: {1: None}}}, 2: 2, 3: None}
print clean(b) # Out: {2: 2}
c = {1: {1: {1: None, 2: {1: None}}}, 2: 2, 3: 0}
print clean(c) # Out: {2: 2, 3: 0}
Brian L. Troutwine wrote:
I've got a problem that I can't seem to get my head around and hoped
somebody might help me out a bit:
I've got a dictionary, A, that is arbitarily large and may contains
ints, None and more dictionaries which themselves may contain ints,
None and more dictionaries. Each of the sub-dictionaries is also
arbitrarily large. When pretty printing A, in the context I'm using A
for, it's rather helpful to remove all key:value pairs where value is
None. So I'd like to be able to define a function dict_sweep to recurse
through A and del all the keys with None as a value.
I feel like the solution is right on the tip of my tounge, so to speak,
but I just can't quite get it. Anyway, here's the best I've come up
with:
How about this:
def dict_sweep(dictionary):
for k, v in dictionary.items():
if v is None:
del dictionary[k]
if type(v) == type({}):
dict_sweep(v)
#if len(v) == 0:
# del dictionary[k]
A_in = {1: {2: 2, 3: {1: None, 2: 2}}, 2: 2, 3: None}
B_in = {1: {1: {1: None, 2: {1: None}}, 2: 2, 3: None}}
dict_sweep(A_in)
dict_sweep(B_in)
print A_in
print B_in
>>{1: {2: 2, 3: {2: 2}}, 2: 2} {1: {2: 2}}
It doesn't produce the output you expect for B_in, but your brackets didn't
match and I'm not sure where the extra close should be. Also, I suspect
you're wanting to delete empty dictionaries but I don't see that mentioned
in the text. If that is so, include the two commented statements.
--
Dale Strickland-Clark
Riverhall Systems - www.riverhall.co.uk be************@lycos.com wrote:
Better:
def clean(d):
for key,val in d.items():
if isinstance(val, dict):
val = clean(val)
if val is None or val == {}:
del d[key]
return d
Can you delete values from a dictionary whilst iterating over its items
?
Fuzzyman http://www.voidspace.org.uk/python/index.shtml
>
a = {1: {2: 2, 3: {1: None, 2: 2}}, 2: 2, 3: None}
print clean(a) # Out: {1: {2: 2, 3: {2: 2}}, 2: 2}
b = {1: {1: {1: None, 2: {1: None}}}, 2: 2, 3: None}
print clean(b) # Out: {2: 2}
c = {1: {1: {1: None, 2: {1: None}}}, 2: 2, 3: 0}
print clean(c) # Out: {2: 2, 3: 0}
Fuzzyman:
Can you delete values from a dictionary whilst iterating over its items ?
Try the code, it works. I am not iterating on the dict, I am not using
dict.iteritems(), that produces a lazy iterable, I am using
dict.items() that produces a list of (key,value) pairs. And I am not
removing elements from that list :-)
Hugs,
bearophile
>
Assuming dict_sweep worked perfectly it would take input like this:
A_in = {1: {2: 2, 3: {1: None, 2: 2}}, 2: 2, 3: None}
B_in = {1: {1: {1: None, 2: {1: None}}, 2: 2, 3: None}
and output this:
A_out = {1: {2: 2, 3: {2: 2}}, 2: 2}
B_out = {2:2}
This dict_sweep above obviously doesn't work and I'm rather afraid of
hitting python's recursion limit. Does anyone see a way to modify
dict_sweep in it's current state to perform dictionary sweeps like
this? What about a non-recursive implementation of dict_sweep?
How about this:
A_in = {1: {2: 2, 3: {1: None, 2: 2}}, 2: 2, 3: None}
def dict_sweep(dictin):
for key in dictin.keys():
if dictin.get(key) == None:
del dictin[key]
elif type(dictin[key]) is dict:
dictin[key] = dict_sweep(dictin[key])
return dictin
A_out = dict_sweep(A_in)
print A_out
Running the above returns:
{1: {2: 2, 3: {2: 2}}, 2: 2}
Regards,
John
--
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.
Would it not be easier to modify the pretty-printer to ignore such
entries rather than have to make a duplicate (I presume you have reason
to need the original dictionary unchanged) dictionary and then delete
entries that match your "ignore" criteria?
Good question. The data I'm handling relates to books: their ISBN,
pricing information, weight, statistical data for each page, citations
in other books to certain pages, those books statistical data, so on
and so forth. It's too much data, really, but this is what I'm tasked
with handling.
Currently I'm just pretty printing the data, but I'm really cheating
right now. The tool I'm writing is supposed to just collect the data,
strip out all the extranious data based on filters defined at the start
of the collection process and then output all that data to stdout,
where it will be caught by a tool to properly format and display it.
Yesterday morning I got into work, went into deep hack mode, wrote the
entire tool and at the end of the day could not, for the life of me,
figure out the recursion I needed. I suppose I'd spent myself. Who
knows?
Anyway, you are right in that if I did indeed need the original
dictionary unchanged it would be much, much easier to modify the
pretty-printer.
Dennis Lee Bieber wrote:
On 13 Sep 2006 16:08:37 -0700, "Brian L. Troutwine"
<go*************@gmail.comdeclaimed the following in comp.lang.python:
arbitrarily large. When pretty printing A, in the context I'm using A
for, it's rather helpful to remove all key:value pairs where value is
None. So I'd like to be able to define a function dict_sweep to recurse
through A and del all the keys with None as a value.
I feel like the solution is right on the tip of my tounge, so to speak,
but I just can't quite get it. Anyway, here's the best I've come up
with:
Would it not be easier to modify the pretty-printer to ignore such
entries rather than have to make a duplicate (I presume you have reason
to need the original dictionary unchanged) dictionary and then delete
entries that match your "ignore" criteria?
--
Wulfraed Dennis Lee Bieber KD6MOG wl*****@ix.netcom.com wu******@bestiaria.com HTTP://wlfraed.home.netcom.com/
(Bestiaria Support Staff: we******@bestiaria.com) HTTP://www.bestiaria.com/
This is a general reply to all.
Thanks for all the suggestions. I hadn't really thought about filtering
empty dictionaries because the data I'm processing won't have them, but
it does make for a much nicer, more general filter. I did end up using
bearophileH's code, but that's mostly because he got there first. Each
solution functioned as advertised.
Again, thanks for all the help. This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Charlotte Henkle |
last post by:
Hello;
I'm pondering how to count the number of times an item appears in
total in a nested list. For example:
myList=,,]
I'd like to know that a appeared three times, and b appeared twice,...
|
by: Donnal Walter |
last post by:
The following method is defined in one of my classes:
def setup(self, items={}):
"""perform setup based on a dictionary of items"""
if 'something' in items:
value = items
# now do something...
|
by: B0nj |
last post by:
I've got a class in which I want to implement a property
that operates like an indexer, for the various colors
associated with the class.
For instance, I want to be able to do 'set' operations...
|
by: Antoine |
last post by:
I would like to construct my own list of items in a grid/ table/ item list
layout but I have a problem. I want to add a sort of index row based on
time, such as there might be blank values.
Sure...
|
by: Jake Emerson |
last post by:
I'm attempting to build a process that helps me to evaluate the
performance of weather stations. The script below operates on an MS
Access database, brings back some data, and then loops through to...
|
by: georgehernando |
last post by:
I am looking for an efficient way to delete the elements of a Python dictionary based on an evaluation of the element's value.
Delete all elements with value bigger than x.
Thanks
|
by: Rich Shepard |
last post by:
I want to code what would be nested "for" loops in C, but I don't know the
most elegant way of doing the same thing in python. So I need to learn how
from you folks. Here's what I need to do: build...
|
by: IamIan |
last post by:
Hello,
I'm writing a simple FTP log parser that sums file sizes as it runs. I
have a yearTotals dictionary with year keys and the monthTotals
dictionary as its values. The monthTotals dictionary...
|
by: Gary Herron |
last post by:
Dan Upton wrote:
Yes. Create a list of keys, and loop through it:
pids = procs_dict.keys()
for pid in pids:
if procs_dict.poll() != None
# do the counter updates
del procs_dict
Then the...
|
by: isladogs |
last post by:
The next Access Europe meeting will be on Wednesday 2 August 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM)
The start time is equivalent to 19:00 (7PM) in Central...
|
by: erikbower65 |
last post by:
Using CodiumAI's pr-agent is simple and powerful. Follow these steps:
1. Install CodiumAI CLI: Ensure Node.js is installed, then run 'npm install -g codiumai' in the terminal.
2. Connect to...
|
by: erikbower65 |
last post by:
Here's a concise step-by-step guide for manually installing IntelliJ IDEA:
1. Download: Visit the official JetBrains website and download the IntelliJ IDEA Community or Ultimate edition based on...
|
by: kcodez |
last post by:
As a H5 game development enthusiast, I recently wrote a very interesting little game - Toy Claw ((http://claw.kjeek.com/))。Here I will summarize and share the development experience here, and hope it...
|
by: Taofi |
last post by:
I try to insert a new record but the error message says the number of query names and destination fields are not the same
This are my field names
ID, Budgeted, Actual, Status and Differences
...
|
by: DJRhino |
last post by:
Private Sub CboDrawingID_BeforeUpdate(Cancel As Integer)
If = 310029923 Or 310030138 Or 310030152 Or 310030346 Or 310030348 Or _
310030356 Or 310030359 Or 310030362 Or...
|
by: lllomh |
last post by:
Define the method first
this.state = {
buttonBackgroundColor: 'green',
isBlinking: false, // A new status is added to identify whether the button is blinking or not
}
autoStart=()=>{
|
by: lllomh |
last post by:
How does React native implement an English player?
|
by: DJRhino |
last post by:
Was curious if anyone else was having this same issue or not....
I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...
| |