Dictionary compare or elif

This is the place for queries that don't fit in any of the other categories.

Dictionary compare or elif

Postby KHarvey » Thu Apr 04, 2013 9:43 pm

I promise this weekend I will sit down and try to learn classes as I need to start working on my tkinter projects again but...

I am attempting to clean up some output from some commands before I submit them to a database. The command output is something like this (the x's are just random words, numbers and letters that I won't use and I can't parse around):
Code: Select all
xxxxx Windows 2000 Version 5.0 xxxxxx
xxxxx Windows 2000 Version 5.2 xxxxxx
xxxxxxx HP ETHERNET JETDIRECT xxxxxx
Cisco IOS Software xxx xx xxxx x


Before I was doing finds looking for the info that I wanted and then putting it into a readable format. But setrofim talked me out of finds so my code looks something like this:
Code: Select all
for ip, fqdns_scans_oss in fqdns_scans_raw.iteritems():
   os = fqdns_scans_oss[2]
   fqdns = fqdns_scans_oss[0]
   scan_type = fqdns_scans_oss[1]
   if "Windows 2000 Version 5.0" in os:
      fqdns_scan_os_parsed[ip] = (fqdns, scan_type, "Windows Server 2000")
   elif "Windows 2000 Version 5.2" in os:
      fqdns_scan_os_parsed[ip] = (fqdns, scan_type, "Windows Server 2003")
   elif "HP ETHERNET JETDIRECT" in os:
      fqdns_scan_os_parsed[ip] = (fqdns, scan_type, "HP Printer")
   elif "Cisco IOS Software" in os:
      fqdns_scan_os_parsed[ip] = (fqdns, scan_type, "Cisco Switch")
       else:
                fqdns_scan_os_parsed[ip]


While this works, it just becomes quite big as I am comparing around 30 outputs.

So after I was done typing all of my elif's I thought, what if I put all of my comparisons in a dictionary. (Please note this is non tested pseudo code)
Code: Select all
os_parsed = {"Windows 2000 Version 5.0":"Windows Server 2000", "Windows 2000 Version 5.2":"Windows Server 2003", "HP ETHERNET JETDIRECT":"HP Printer", "Cisco IOS Software":"Cisco Switch"}
for raw, parsed in os_parsed:
   for ip, fqdns_scans_oss in fqdns_scans_raw.iteritems():
      os = fqdns_scans_oss[2]
      fqdns = fqdns_scans_oss[0]
      scan_type = fqdns_scans_oss[1]
      if raw in os:
         fqdns_scan_os_parsed[ip] = (fqdns, scan_type, parsed)


I think the dictionary looks much cleaner, but I have some concerns with it.
While my os_parsed has only 30'ish items in it, my fqdns_scans_oss has a couple thousand so I think I would want to switch the order that it runs in. But I haven't quite wrapped my head around how I would code it. Maybe something like this:
Code: Select all
os_parsed = {"Windows 2000 Version 5.0":"Windows Server 2000", "Windows 2000 Version 5.2":"Windows Server 2003", "HP ETHERNET JETDIRECT":"HP Printer", "Cisco IOS Software":"Cisco Switch"}
for ip, fqdns_scans_oss in fqdns_scans_raw.iteritems():
   os = fqdns_scans_oss[2]
   fqdns = fqdns_scans_oss[0]
   scan_type = fqdns_scans_oss[1]
   if os_parsed in os:
      fqdns_scan_os_parsed[ip] = (fqdns, scan_type, Something I haven't figured out)


That looks a bit cleaner other that the "Something I haven't figured out" part. Sorry it has been a long day.

I think my biggest concern would be speed. If I go through the elif's then when a match is found it moves on in the code without processing the rest of the elif's. So for example if the first if "Windows 2000 Version 5.0" is matched then it won't process Version 5.2, JETDIRECT, or Cisco IOS Sofware.
But if I use a dictionary compare then I will compare every value to every value each time. I could use breaks in the loops to cut down on the processing time, but that might be ugly.
Now that I think about it, I guess it wouldn't add that much time to the processing, maybe a second or two, but I am not sure if that is the way to do it.

So my question would be:
Is the dictionary path the way that I should go to do all of these comparisons?
KHarvey
 
Posts: 34
Joined: Tue Mar 19, 2013 5:13 pm
Location: US

Re: Dictionary compare or elif

Postby setrofim » Fri Apr 05, 2013 2:23 am

KHarvey wrote:I could use breaks in the loops to cut down on the processing time, but that might be ugly.

That's exactly what you should be doing -- that's what the break statement is for.
Code: Select all
os_parsed = {"Windows 2000 Version 5.0": "Windows Server 2000",
             "Windows 2000 Version 5.2": "Windows Server 2003",
             "HP ETHERNET JETDIRECT": "HP Printer",
             "Cisco IOS Software": "Cisco Switch"}

for ip, fqdns_scans_oss in fqdns_scans_raw.iteritems():
    os = fqdns_scans_oss[2]
    fqdns = fqdns_scans_oss[0]
    scan_type = fqdns_scans_oss[1]
     
    for raw, parsed in os_parsed.iteritems():
        if raw in os:
            fqdns_scan_os_parsed[ip] = (fqdns, scan_type, parsed)
            break


KHarvey wrote:So my question would be:
Is the dictionary path the way that I should go to do all of these comparisons?

Well, you're trying to map one set of values onto another set of values, so yeah, a dict is the natural structure to specify the mapping.

There are a couple of other ways to do the actual mapping itself (e.g. with regular expressions, or stripping away junk from the raw value and then indexing directly into the dict), but in this cases, I don't think those would give you any benefit, performance or readability wise, over what you're currently doing.
setrofim
 
Posts: 288
Joined: Mon Mar 04, 2013 7:52 pm


Return to General Coding Help

Who is online

Users browsing this forum: bill z and 4 guests