-1

I have a defaultdict(lambda: defaultdict(list))

jenkins_job_dict = defaultdict(<function <lambda> at 0x10428b230> , {
    'newswires': defaultdict(<type 'list'> , {
        'commodities': ['blue_virginia', 'green_virginia'],
        'nss_autopub_launch': ['blue_virginia'],
        'sample': ['blue_oregon', 'blue_virginia'],
        'commodities_efs': ['blue_virginia'],
        'gnews': ['blue_virginia']
    }),
    'usr': defaultdict(<type 'list'> , {
        'gatekeeper': ['blue_virginia'],
        'membership_services': ['green_virginia'],
        'membership_micro_db': ['green_virginia'],
        'pam_ml': ['blue_virginia', 'green_virginia'],
        'pam_rds': ['blue_virginia'],
        'preferences_api_db': ['blue_virginia', 'green_virginia'],
        'cs_microservice': ['blue_virginia'],
        'sample': ['blue_oregon', 'blue_virginia'],
        'preferences_api': ['blue_virginia'],
        'pam_app': ['blue_virginia', 'green_virginia']
    })
})

I need to pop the first key,value from the values. So pop one at a time from both keys (within the key key doesnt have to be ordered) :

'commodities': ['blue_virginia', 'green_virginia']
'gatekeeper': ['blue_virginia']
'nss_autopub_launch': ['blue_virginia'] 
'membership_services': ['green_virginia']
…

I have the following code :

def create_jenkins_job_dict(all_jobs):
    jenkins_job_dict = defaultdict(lambda: defaultdict(list))
    for job in all_jobs:
        if job.startswith("djin_a"):
            stackname = job.split('_', 2).pop(2)
            lz = job.split('_', 2).pop(1)[1:]
            stack_info = parse_stack_info(stackname, lz)
            if stack_info is not None:
                for key, value in stack_info.items():
                    if (value == "up"):
                        jenkins_job_dict[lz][stackname].append(key)
    return jenkins_job_dict

all_jobs = ['cost_explorer', 'cucumber', 'cucumber_reporter', 'cucumber_stacks_cleanup', 'cucumber_stacks_single_account', 'cucumber_stacks_update', 'deptwo.0-workflow', 'dispatcher-policy-setup', 'djin_abuild_active_directory_iandp_domains', 'djin_abuild_artifactory', 'djin_abuild_barrage_slaves', 'djin_abuild_cf_test_1', 'djin_abuild_epam', 'djin_abuild_epportal', 'djin_abuild_gate', 'djin_abuild_groups', 'djin_abuild_hostname_dispatcher_2', 'djin_abuild_jenkins_slaves', 'djin_abuild_netapp_ontap', 'djin_abuild_papi', 'djin_abuild_pibsec_se', 'djin_abuild_sonar_slave', 'djin_abuild_sonarqube', 'djin_acntsvc_category_manager', 'djin_acntsvc_consumer_search_marklogic_db', 'djin_acntsvc_searchh'] # list of names of jobs in jenkins.
jenkins_job_dict = create_jenkins_job_dict(all_jobs) # basically produces the above dict.
while jenkins_job_dict:
    stack_list = jenkins_job_dict.pop(min(jenkins_job_dict,key=jenkins_job_dict.get))
    stack = stack_list.pop(min(stack_list, key=stack_list.get))
    print (stack)

This doesnt get what I need , whats the most pythonic way of doing this ?

Scooby
  • 3,371
  • 8
  • 44
  • 84
  • "So pop in this order": A dictionary (i.e., a hash table) is by definition unordered. If you want to access the keys and values in a specific order, you should have the keys ordered in the order you desire (e.g. in a list) elsewhere beforehand – Niema Moshiri Jan 18 '18 at 17:50
  • to make it reproducible, can you provide the code that creates this `jenkins_job_dict` `dictionary`? – Tony Jan 18 '18 at 17:55
  • @Niema Moshiri That is why he/she is using a `defaultdict` from `collections` rather than the built-in `dict` `type`. – Tony Jan 18 '18 at 17:57
  • @NiemaMoshiri - it does not have to be ordered, just need to pop one at a time. – Scooby Jan 18 '18 at 17:59
  • 1
    @Tony I thought `defaultdict` is also unordered? I thought `OrderedDict` was the only ordered dictionary – Niema Moshiri Jan 18 '18 at 18:00
  • @Tony - see edit now – Scooby Jan 18 '18 at 18:02
  • @Niema Moshiri you are absolutely right! I mistook for the ordered one – Tony Jan 18 '18 at 18:04
  • @NiemaMoshiri - So pop one at a time from both keys (within the key key doesnt have to be ordered) : – Scooby Jan 18 '18 at 18:05
  • @Scooby you need to define all_jobs as well since you're passing it as a parameter to your function :) – Tony Jan 18 '18 at 18:07
  • @Tony - Done. Its basically just a list of names of jobs from jenkins – Scooby Jan 18 '18 at 18:09
  • @Scooby I think you might be missing a bit on the concept of reproducible example. Now you need to do the same with `jenkins` as you're calling `jenkins.keys()`. One needs to be able to get exactly what you are getting just by running your code snippet. – Tony Jan 18 '18 at 18:14
  • @Tony - got it, updated again with full context. You won't be able to just run it as is since you need a jenkins w (u/p) but the code is all there now. – Scooby Jan 18 '18 at 18:18
  • @scooby so with the `defaultdict` posted, you just want to print the output desired? – salparadise Jan 18 '18 at 18:19
  • @salparadise - yes, just need to grab and pop one key, value from values at a time. – Scooby Jan 18 '18 at 18:21
  • @Scooby well it's still not reproducible then. IMHO, you need to use another `defaultdict` as an example, which you are going to create in full in your code sample, and then take the knowledge you'll acquire from the answers you'll get to your actual `defaultdict` that you are working with. – Tony Jan 18 '18 at 18:22
  • @scooby is popping actually required to get the output? (there is other ways) – salparadise Jan 18 '18 at 18:23
  • I'm assuming OP wants to `pop()` to free up some memory after it's set to a new list? It's a bit unclear what exactly the OP is trying to achieve here by popping the values. I agree, there might be a better way to achieve what OP is actually trying to do. – r.ook Jan 18 '18 at 18:24
  • @Tony - gotcha, rewritten to make it completely reproducible. You should be able to run with it now – Scooby Jan 18 '18 at 18:26
  • @salparadise - Basically need to read a key, value from values and then remove it from the dict.Popping seemed the best fit for that. Anything else that produces the same effect will be okay as well – Scooby Jan 18 '18 at 18:27
  • @Scooby, `parse_stack_info` is undefined... – r.ook Jan 18 '18 at 18:30
  • What I'm trying to understand is, if you end up disposing the dictionary anyhow, why not just parse and return the relevant data during your `create_jenkins_job_dict()`? It should be trivial to modify the function to return the key/value one at a time instead of adding to a dictionary *and then* popping and disposing it. Feels like that's complicating your problem. – r.ook Jan 18 '18 at 18:33

1 Answers1

2

Is this what you are looking for:

outer={'a':{'b':[1,2,3], 'c':[4,5,6]}, 'd':{'e':[7,8,9], 'f':[10,11,12]}}
while outer:
    outer_key, inner = outer.popitem()
    while inner:
        inner_key, inner_value = inner.popitem()
salparadise
  • 5,699
  • 1
  • 26
  • 32
Michael Robellard
  • 2,268
  • 15
  • 25