字典键的子集

时间:2016-07-25 10:48:01

标签: python dictionary

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

我需要一个具有唯一IP地址的ip:port组合列表,端口可以是原始密钥中出现的任何端口。例如,上面提到了两种变体:['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]

我不喜欢它,因为它会创建其他列表然后丢弃它们。

3 个答案:

答案 0 :(得分:7)

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

if(another == null)
    return 1; // If you want nulls in the back, return -1

然后从不同的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']}

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

{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'} 需要对输入数据进行排序。因此,如果您想避免对dict中的所有键进行排序,则应该只使用groupby已见过的键。

set

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

答案 1 :(得分:4)

执行此操作的一种方法是将密钥转换为自定义类,该类仅在执行相等性测试时查看字符串的IP部分。它还需要提供适当的__hash__方法。

这里的逻辑是set构造函数将“看到”具有相同IP的密钥相同,忽略比较中的端口部分,因此如果密钥具有该密钥,则将避免向该组添加密钥IP已存在于集合中。

这是在Python 2或Python 3上运行的一些代码。

class IPKey(object):
    def __init__(self, s):
        self.key = s
        self.ip, self.port = s.split(':', 1)

    def __eq__(self, other):
        return self.ip == other.ip

    def __hash__(self):
        return hash(self.ip)

    def __repr__(self):
        return 'IPKey({}:{})'.format(self.ip, self.port)

def get_uniq_worker_ips(workers):
    return [k.key for k in set(IPKey(k) for k in workers)]

# Test

workers = {
    'ip1:port1' : "val", 
    'ip1:port2' : "val", 
    'ip2:port1' : "val", 
    'ip2:port2' : "val", 
}

print(get_uniq_worker_ips(workers))    

<强>输出

['ip2:port1', 'ip1:port1']

如果您运行的是Python 2.7或更高版本,该函数可以在set()构造函数调用中使用集合理解而不是该生成器表达式。

def get_uniq_worker_ips(workers):
    return [k.key for k in {IPKey(k) for k in workers}]

IPKey.__repr__方法并非绝对必要,但我希望我的所有课程都为__repr__,因为它在开发过程中非常方便。

这是一个更加简洁的解决方案,非常有效,由Jon Clements提供。它通过字典理解构建所需的列表。

def get_uniq_worker_ips(workers):
    return list({k.partition(':')[0]:k for k in workers}.values())

答案 2 :(得分:0)

我在解决方案中更改了几个字符,现在对此感到满意。

$(function () {
    $("input").on("mouseover", function () {           
        var a = $(this).attr('name');
        populate(a);
    });
});

感谢@Ignacio Vazquez-Abrams和@ M.T.解释。