【问题标题】:Python Dynamic Dictionary, Multi-Value Per Key CountingPython 动态字典,每键多值计数
【发布时间】:2018-02-23 02:23:30
【问题描述】:

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

问题在于,网络团队可以随时添加新的路由器型号、将软件升级到未知版本或其他任何方式,通过为每种路由器类型、软件版本和依此类推,需要对脚本进行持续维护,而我不想这样做,因此我将所有变量设为动态。它遍历文件,找到正确的软件类型、版本和模型(因为每个供应商通常不会更改版本之间的呈现方式)。然后将变量分配为“模型”、“类型”和“版本”,然后将其打印出来。

我希望能够将 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

【问题讨论】:

    标签: python dictionary counting


    【解决方案1】:

    也许 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 值。您的列数必须与值列表的长度一样多。

    groupbysize 的其他示例可以在这里找到: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())
    

    【讨论】:

    • 这看起来是一个很好的解决方法,但功能有问题: Traceback(最近一次调用最后一次):文件“software-versions.py”, df 中的第 111 行。 columns =['model', 'type', 'version'] ..... .... ValueError: Length mismatch: Expected axis has 6 elements, new values have 3元素 不确定是什么导致了这个错误。从来没有使用过 panads 库,所以我不确定这个轴和元素是如何工作的。
    • 你的字典变了吗?在您的示例中,每个键(路由器)都有一个包含三个值('model'、'type'、'version')的列表。确保标记每一列。例如,如果您的 dict 包含 ('model', 'type', 'version','foo','bar') 之类的值,请执行以下操作: df.columns = ['model', 'type', 'version',' foo','bar'].
    • 我相信当值被放入字典时,它可能会得到不可见的东西,如 /n /s /t 或类似的东西,这些东西被算作附加列。因此,我没有在我的脚本中执行和剥离()、lstrip()或rstrip(),我将在稍后执行并执行,我只是在末尾添加了'','',''列定义。它修复了错误并且输出是完美的。非常感谢您的帮助,我真的很感激!!!
    猜你喜欢
    • 2011-06-09
    • 2023-03-08
    • 1970-01-01
    • 2023-04-06
    • 2016-11-05
    • 2012-12-01
    • 2019-11-21
    • 2021-08-19
    • 1970-01-01
    相关资源
    最近更新 更多