Python: Get items at depth? (set library?)
I have a nested list something like this:
PLACES = (
('CA', 'Canada', (
('AB', 'Alberta'),
('BC', 'British Columbia' (
('van', 'Vancouver'),
),
...
)),
('US', 'United States', (
('AL', 'Alabama'),
('AK', 'Alaska'),
...
I need to retrieve some data out of it. If depth
is 开发者_开发技巧0
I need to retrieve all the countries (and their codes), if depth == 1
, I need to retrieve all the states/provinces, if depth == 2
I need to retrieve all the cities... and so forth. Is there some set library for doing stuff like this? Or can someone point me in the right direction? I started coding up a solution only to realize it wouldn't work for levels deeper than 1 because you have to go in and out of each list...
Also notice that not all items have a 3rd part (i.e., we're pretending Alberta doesn't have any cities, so retrieving items at depth 2 would just return ('van','Vancouver')
in this limited scenario).
I didn't realize this before, but I also needed the parent value. So, I modified interjay's solution:
def depth_gen(seq, depth, par=None):
if depth==0:
for x in seq:
yield par, x[0], x[1]
return
for x in seq:
if len(x)==3:
par = x[0]
for y in depth_gen(x[2], depth-1, par):
yield y
Which I'm using to generate some HTML:
<label for="id-pickup_address-province">Province</label>
<select id="id-pickup_address-province" rel="pickup_address-country" name="pickup_address-province">
<option rel="CA" value="AB">Alberta</option>
<option rel="CA" value="BC">British Columbia</option>
<option rel="CA" value="MB">Manitoba</option>
...
<option rel="US" value="WV">West Virginia</option>
<option rel="US" value="WI">Wisconsin</option>
<option rel="US" value="WY">Wyoming</option>
</select>
<label for="id-pickup_address-country">Country</label>
<select id="id-pickup_address-country" name="pickup_address-country">
<option value="CA">Canada</option>
<option value="US">United States</option>
</select>
And then I should be able to easily filter the list with jQuery based on which country is selected...
Here is a solution which will work for any depth:
def depthGenerator(seq, depth):
if depth==0:
for x in seq:
yield x[:2] #strip subsequences
return
for x in seq:
if len(x)==3: #has subsequence?
for y in depthGenerator(x[2], depth-1):
yield y
Example:
>>> list(depthGenerator(PLACES, 1))
[('AB', 'Alberta'), ('BC', 'British Columbia'), ('AL', 'Alabama'), ('AK', 'Alaska')]
Suggestion, don't use nested lists. Create some kind of real structure of classes that gives you more information and organization. It will make it easier to think about, easier to code and easier for other people to read.
This is what I see:
for (county, countryName, stateTuple) in MyTuple:
for (state, stateName, CountyTuple) in stateTuple:
...
and so on, which is a repeating pattern.
def extract( myTuple, level ):
if level:
return ( item[2] for item in myTuple if len(item) == 3)
else:
return ( (item[0], item[1]) for item in myTuple )
Then call extract as many times as you need for your "depth".
精彩评论