在打印相应值时跳过特定迭代的重复值 - 我的最终目标是将其写入 CSV 文件

我试图在我的代码中使用 set() 来跳过迭代中的重复值;此类问题可能已在 SO 上得到解答,但是当我尝试在我的脚本中执行此操作时,我没有得到所需的输出。


我正在使用 device['name'] 提取设备名称,API 中的 IP 地址为;这是 IP 地址的此类设备的 API 响应主体:


"DTO": [

  {

    "id": "3485893021",

    "name": "Alternate Addresses",

    "IPAddress": [

      "10.228.143.125",

      "10.228.143.253",

      "10.229.184.125",

      "10.229.184.134",

      "192.21.247.125",

      "192.21.247.188",

      "192.21.247.226",

      "192.21.247.254",

      "192.21.247.61",

      "192.21.247.92",

      "192.168.53.38",

      "192.128.167.74"

     ]

我有一个像上面一样的单个设备的多个 IP,但是当我尝试这个时,我将所有迭代的设备名称设为 None 并且只打印来自各个设备的第一个 IP。我想要的是打印所有 IP 并只打印一次它们对应的设备名称。我正在从 API 中提取这些数据。


seen = set()

seen_add = seen.add

for device in data:

    fqdn = device['name']

    for ips in device["DTO"][0]["IPaddress"]:

        if fqdn not in seen:

            print(ips, seen_add(fqdn))

这是输出:


10.228.143.125 None

10.23.54.6.8 None

10.23.6.1 None

10.22.16.34 None

10.122.25.189 None

我在 python 控制台输出中期待这个:


10.228.143.125 10.228.143.253 10.229.184.125 10.229.184.134 192.21.247.125 192.21.247.188 192.21.247.226 192.21.247.254 192.21.247.61 192.21.247.92 192.168.53.38 192.128.167.74 devicename1

等等其他此类设备......


更新:这个完全按照我想要的方式打印,但是现在当我尝试在 CSV 文件上打印它时,fqdn 和 ipaddresses 开始分崩离析。谁能帮助我以更简单的方式写这个?


for device in data:

    fqdn = device['name']

    if fqdn not in entries:

        entries.add(fqdn)

        print("\nDevice: %s" % fqdn)

    for ips in device["DTO"][0]["IPaddress"]:

                try:

                    ipaddress.ip_address(ips)

                    print(ips)

                except ValueError:

                    print("Not Found")

python控制台上的输出:


Device: Device1

Not Found


Device: Device2

Not Found


Device: Device3

10.228.143.125

10.228.143.253

10.229.184.125

10.229.184.134

192.21.247.125

192.21.247.188

192.21.247.226

我试过这个打印在一个 csv 文件上:


with open("BNA API.csv", 'w', newline='') as f:

    fieldname = ['BNA Name', 'IP Addresses']

    writer = csv.DictWriter(f, fieldnames=fieldname)

    writer.writeheader()




烙印99
浏览 192回答 3
3回答

红糖糍粑

使用这个数据集来测试代码:data = [  {    "name": "device1",    "vendorName": "Cisco",    "DTO": [      {        "id": "426945997-254",        "name": "Category",        "IPaddress": [          "10.228.143.125",          "10.228.143.253",          "10.229.184.125",          "10.229.184.134",          "192.21.247.125"         ],       }     ]   },   {    "name": "device2",    "vendorName": "Cisco",    "DTO": [      {        "id": "426945997-254",        "name": "Category",        "IPaddress": [         ],       }     ]   },   {    "name": "device3",    "vendorName": "Cisco",    "DTO": [      {        "id": "426945997-254",        "name": "Category",       }     ]   } ]我不确定你到底在做什么,因为你的代码与键名不匹配,但这应该适合你import csv with open("BNA API.csv", 'w', newline='') as f:    fieldname = ['BNA Name', 'IP Addresses']    writer = csv.DictWriter(f, fieldnames=fieldname)    writer.writeheader()with open("BNA API.csv", 'a', newline='') as f:    for device in data:        fqdn = device['name']           try:            ips = ' '.join(set(device["DTO"][0]["IPaddress"])) or "not found"        except KeyError:            ips = "not found"        writer = csv.writer(f)        writer.writerow([fqdn, ips])ips = ' '.join(set(device["DTO"][0]["IPaddress"])) or "not found"正在检查,如果IP地址为空的清单是用Python的True-Y检测的意义如果集合返回空它会采取"not found"替代编辑:似乎这个问题还有更多内容,如果您的 IP 地址不正确或没有什么,您可以' '.join()像这样使用过滤器:bad_list = ['Firewall','Load something']#...#same codetry:    ips = ' '.join(x for x in set(device["DTO"][0]["IPaddress"]) if x not in bad_list) or "not found"if x not in bad_list在将其添加到 之前的检查.join(),您可以将其视为在遍历列表时的过滤器。如果您不想键入要排除的所有内容,您可以将其更改为if ipaddress(x)并编写一个调用的函数ipaddress(x),如果它是有效的 ipaddress,则返回 True,如果不是,则返回 false。

德玛西亚99

两个建议:1) seen_add做了一些事情,但它不返回任何东西,这就是给你 None 的。2)如果你不希望它们被换行分开,你不能在for循环中打印,你只需要一个打印。您可以随时构建字符串:out_str = out_str + ' ' + ips如果你不关心顺序,一点点展平应该可以工作:print(' '.join{ips for device in data for ips in device["DTO"][0]["IPaddress"]})
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python