对于一个键值,计算字典列表中其他键值的出现

时间:2019-12-21 14:00:42

标签: python python-3.x

我正在从只有2个键的大列表中创建字典的子列表。我的数据是这样的:

[{'query_name': 'google.com', 'ip4_address': '1.1.1.1' } , {'query_name': 'google.com','ip4_address': '2.2.2.2'}, {'query_name': 'google.com', 'ip4_address': '3.3.3.3'}]

我想找出特定“ query_name”的“ ip4_address”的唯一出现次数,并将所有“ ip4_address”合并到单个字典中

输出示例:

['query_name': 'google.com', 'ip4_address': '1.1.1.1' ,'2.2.2.2', '3.3.3.3', 'count': '3' }]

这是我的代码:

reader = DataFileReader(open((os.path.join('active_dns', filename)), "rb"), DatumReader())

for user in reader:
    keys = ['query_name', ,'ip4_address']
    all_values =dict((key, user[key]) for key in keys)
    a_lst.append(all_values)

到目前为止,我已经尝试过将两个键进行比较并使计数器递增以获取重复值:

counterdict = defaultdict(list)

for d in a_lst:
       counterdict[d['ip4_address']][d['query_name']] += 1 

但是到目前为止没有期望的结果。任何帮助表示赞赏。

5 个答案:

答案 0 :(得分:2)

您可以使用以下方法获得所需的结果:

from collections import defaultdict
a_lst=[{'query_name': 'google.com', 'ip4_address': '1.1.1.1' } , 
{'query_name': 'google.com','ip4_address': '2.2.2.2'}, {'query_name': 
'google.com', 'ip4_address': '3.3.3.3'},{'query_name': 'yahoo.com', 
'ip4_address': '3.3.3.3'}]

query_dict=defaultdict(set)
for d in a_lst:
  query_dict[d['query_name']].add(d['ip4_address'])

counterlist = []
for q in query_dict:
  cdict={}
  cdict['query_name'] = q
  cdict['ip4_address'] = list(query_dict[q])
  cdict['count'] = len(cdict['ip4_address'])
  counterlist.append(cdict)

print(counterlist)

输出为:

[{'query_name': 'google.com', 'ip4_address': ['3.3.3.3', '2.2.2.2', '1.1.1.1'], 'count': 3}, {'query_name': 'yahoo.com', 'ip4_address': ['3.3.3.3'], 'count': 1}]

答案 1 :(得分:0)

因此,可以通过使用itertools.groupby来实现。需要注意的是,必须对数据进行预排序才能使其正常工作。

from itertools import groupby
from operator import itemgetter

data = [{'query_name': 'google.com', 'ip4_address': '1.1.1.1' } , {'query_name': 'google.com','ip4_address': '2.2.2.2'}, {'query_name': 'google.com', 'ip4_address': '3.3.3.3'}, {'query_name': 'google.com', 'ip4_address': '1.1.1.1' }, {'query_name': 'google.com', 'ip4_address': '1.1.1.1' }]

query = itemgetter('query_name')
ip = itemgetter('ip4_address')

def custom_sort(obj):
    q = query(obj)
    i = ip(obj)
    return (q, i)

for k, v in groupby(sorted(data, key=custom_sort), key=custom_sort):
    base = {'query_name': k[0], 'ip4_address': k[1]}
    base.update({'count': len(list(v))})
    print(base)

{'query_name': 'google.com', 'ip4_address': '1.1.1.1', 'count': 3}
{'query_name': 'google.com', 'ip4_address': '2.2.2.2', 'count': 1}
{'query_name': 'google.com', 'ip4_address': '3.3.3.3', 'count': 1}

答案 2 :(得分:0)

您可以使用熊猫轻松地做到这一点。

import pandas as pd
l = [{'query_name': 'google.com', 'ip4_address': '1.1.1.1' } , {'query_name': 'google.com','ip4_address': '2.2.2.2'}, {'query_name': 'google.com', 'ip4_address': '3.3.3.3'},{'query_name': 'yahoo.com', 'ip4_address': '1.1.1.2' }]
df = pd.DataFrame(l)
ips=df.groupby(by='query_name')['ip4_address'].value_counts()
ip_dict=ips.to_dict() 

答案 3 :(得分:0)

这是另一种方法。

data = [{'query_name': 'google.com', 'ip4_address': '1.1.1.1'},
        {'query_name': 'google.com', 'ip4_address': '2.2.2.2'},
        {'query_name': 'google.com', 'ip4_address': '3.3.3.3'}]

def get_ip4(data_list, query_name):
    return { x["ip4_address"] for x in data_list if x["query_name"]==query_name }

query_name = "google.com"

my_desired_output = {k: v for k, v in 
    zip(['query_name', 'ip4_address', 'count'],
        [query_name, list(get_ip4(data, query_name)), len(list(get_ip4(data, query_name)))])}

答案 4 :(得分:0)

嗯,“鼻子上的”解决方案怎么样?

data = [
    {'query_name': 'google.com', 'ip4_address': '1.1.1.1'},
    {'query_name': 'google.com', 'ip4_address': '2.2.2.2'},
    {'query_name': 'google.com', 'ip4_address': '3.3.3.3'}
]

query_name = "google.com"

ip_addresses = [d["ip4_address"] for d in data if d["query_name"] == query_name]

new_data = {
    "query_name": query_name,
    "ip4_address": ip_addresses,
    "count": str(len(ip_addresses))
}

如果ip_addresses应该是一个元组或列表,那么从所需的输出中并不会立即显而易见。我确定您知道如何将列表投射到元组。