python - 字典键的子集

标签 python dictionary

我有一个 {'ip1:port1' : <value>, 'ip1:port2' : <value>, 'ip2:port1' : <value>, ...} 形式的 python 字典.字典键是字符串,由 ip:port 对组成。值对于此任务并不重要。

我需要 ip:port 的列表具有唯一 IP 地址的组合,端口可以是出现在原始 key 中的任何端口。例如上面的例子,两个变体是可以接受的:['ip1:port1', ip2:port1']['ip1:port2', ip2:port1'] .

最符合 Python 风格的方法是什么?

目前我的解决方案是

def get_uniq_worker_ips(workers):
    wip = set(w.split(':')[0] for w in workers.iterkeys())
    return [[worker for worker in workers.iterkeys() if worker.startswith(w)][0] for w in wip]

我不喜欢它,因为它会创建额外的列表然后丢弃它们。

最佳答案

您可以使用 itertools.groupby按相同的 IP 地址分组:

data = {'ip1:port1' : "value1", 'ip1:port2' : "value2", 'ip2:port1' : "value3", 'ip2:port2': "value4"}
by_ip = {k: list(g) for k, g in itertools.groupby(sorted(data), key=lambda s: s.split(":")[0])}
by_ip
# {'ip1': ['ip1:port1', 'ip1:port2'], 'ip2': ['ip2:port1', 'ip2:port2']}

然后从不同的 IP 组中选择一个。

{v[0]: data[v[0]] for v in by_ip.values()}
# {'ip1:port1': 'value1', 'ip2:port1': 'value3'}

或者更短,为组中的第一个键创建一个生成器表达式:

one_by_ip = (next(g) for k, g in itertools.groupby(sorted(data), key=lambda s: s.split(":")[0]))
{key: data[key] for key in one_by_ip}
# {'ip1:port1': 'value1', 'ip2:port1': 'value3'}

但是请注意,groupby 需要对输入数据进行排序。因此,如果您想避免对 dict 中的所有键进行排序,您应该只使用一组 set 已经看到的键。

seen = set()
not_seen = lambda x: not(x in seen or seen.add(x))
{key: data[key] for key in data if not_seen(key.split(":")[0])}
# {'ip1:port1': 'value1', 'ip2:port1': 'value3'}

这与您的解决方案类似,但不是循环唯一键并在字典中为每个键找到匹配的键,而是循环键并检查您是否已经看到 IP。

关于python - 字典键的子集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38565727/

相关文章:

python - 如何在计算互补列表时正确处理重复项?

python - py2exe/pyinstaller : Is it bad practice to put all configurable variables in a . py文件?

java - 获取 map 键的数组

python - 合并 Python 字典

dictionary - 同义词词典

python - 从字典创建数据框 - python

python - 在 Python 中使用内置 str() 类型的潜在异常

Python xml - 删除空格以对齐 xml 文档

python - Django:将一堆媒体分组的正确方法

android - 基于位置的服务应用