Python动态字典,每键计数多值

时间:2017-09-14 07:47:19

标签: python dictionary counting

我正在编写一个python脚本来解析1000个Rancid文件,这些文件包含网络上一堆路由器的所有配置信息,型号,软件类型,软件版本等。到目前为止,我已经得到它正确循环所有文件,并通过主机名,软件类型(IE IOS,IOS XR,JUNOSE,JUNOS等)的路由器打印出一个很好的列表路由器,以及软件版本是什么是(IE 12.3R7,15.2(2)T1,12.1.1p0.1等。)。

问题是,因为网络团队可以随时添加新的路由器模型,将软件升级到未知版本,或者其他什么,通过为每种路由器类型,软件版本和添加变量来管理它。因此需要对脚本进行持续维护,而我不愿意这样做,因此我将所有变量都设置为动态。它遍历文件,找到合适的软件类型,版本和模型(因为每个供应商通常不会改变从版本到版本的呈现方式)。然后将变量指定为“model”,“type”和“version”,然后将其打印出来。

我希望能够将argparse添加到我的代码中,以便在需要时而不是打印整个列表时我只能得到一个带有计数的摘要,所以在循环的每次传递期间我都会添加它找到的值每个关键词典的多值。

以下是字典的构建方式,以及如何打印字典。

我将密钥设置为基于主机名的文件名(因此更少解析原始数据以获取更多信息)

key = file
mydict.setdefault(key, [])
mydict[key].append(model)
mydict[key].append(type)
mydict[key].append(version)

#here is an example of what the dictionary looks like
print mydict

{'router1': ['model1', 'JUNOS', '12.3R7'], 'router2': ['model1', 'JUNOS', 
'13.3R4'], 'router3': ['model2', 'IOS', '15.2'], 'router4': ['model3', 
'JUNOS', '11.4R1'], 'router5': ['model2', 'IOS', '15.3'], 'router6': 
['model4', 'JUNOSe', '12.1.1p0.1'], 'router7': ['model1', 'JUNOS', 
'12.3R7'], 'router7': ['model1', 'JUNOS', '12.3R7'], 'router8': ['model1', 
'JUNOS', '13.3R4'], 'router9': ['model2', 'IOS', '15.2'], 'router10': 
['model3', 'JUNOS', '11.4R1'], 'router11': ['model2', 'IOS', '15.3'], 
'router12': ['model5', 'JUNOS', '12.3R7']}

我想要的是一种方法来匹配所有3个值相同的重复项,计算它们,然后将它们打印出一个很好的格式化列表(忽略键,因为打印它无所谓这个练习)

JUNOS    model1 12.3R7 3
JUNOS    model1 13.3R4 2
JUNOS    model3 11.4R1 2
JUNOS    model5 12.3R7 1
IOS      model2 15.2 2
IOS      model2 15.3 2
JUNOSE   model4 12.1.1p0.1 1

或者更优选(但可能更困难)

JUNOS

model1   12.3R7 2
         13.3R4 2
model3   11.4R1 2
model5   12.3R7 1

JUNOSE

model2   12.1.1p0.1 1

IOS

model2   15.2 2
         15.3 2

1 个答案:

答案 0 :(得分:0)

也许Pandas图书馆可以帮助您实现这一目标:https://pandas.pydata.org/index.html
您可以将 mydict 转换为Pandas的 DataFrame ,然后使用 groupby()方法获取所有组。最后使用 size()来计算。

你可以这样做:

import pandas as pd
mydict = {} #your dict here
df = pd.DataFrame.from_dict(mydict,'index')
df.columns=['model','type','version'] #Affect column names to your DF.
print(df.groupby(['type','model','version']).size())

这会给你:

type    model   version   
IOS     model2  15.2          2
                15.3          2
JUNOS   model1  12.3R7        2
                13.3R4        2
        model3  11.4R1        2
        model5  12.3R7        1
JUNOSe  model4  12.1.1p0.1    1

当您使用df.columns=...影响列名称时,请确保它适合您的dict值。您必须具有与值列表长度一样多的列。

groupby 的其他示例,然后 size 可在此处找到:Duplicate rows in pandas DF

编辑 - 字典结构
在我看来,使用dict作为值而非列表更具描述性的 dict 应该会更好,例如:

{'router1': {'bar': None,
  'foo': None,
  'model': 'model1',
  'type': 'JUNOS',
  'version': '12.3R7'},
 'router2': {'bar': None,
  'foo': None,
  'model': 'model1',
  'type': 'JUNOS',
  'version': '13.3R4'},...}

这样pd.DataFrame.form_dict将自动影响列名称。以前的代码将是:

import pandas as pd
mydict = {} #your dict of dicts here
df = pd.DataFrame.from_dict(mydict,'index')
print(df.groupby(['type','model','version']).size())