字典键的子集

wl2*_*776 4 python dictionary

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

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

这种方式最蟒蛇的方式是什么?

目前我的解决方案是

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]
Run Code Online (Sandbox Code Playgroud)

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

tob*_*s_k 7

您可以使用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']}
Run Code Online (Sandbox Code Playgroud)

然后从不同的IP组中选择任何一个.

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

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

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'}
Run Code Online (Sandbox Code Playgroud)

但是,请注意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'}
Run Code Online (Sandbox Code Playgroud)

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