Subset of dictionary keys

I have a python dictionary of form {'ip1:port1' : <value>, 'ip1:port2' : <value>, 'ip2:port1' : <value>, ...}. A key dictionary is a string of ip: port pairs. Values ​​are not important for this task.

I need a list of combinations ip:portwith unique IP addresses, the ports can be any of those that appear among the original keys. For example, two options are acceptable above: ['ip1:port1', ip2:port1']and ['ip1:port2', ip2:port1'].

What is the most pythonic way to do this?

Currently my decision

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]

I don't like this because it creates additional lists and then discards them.

+4
source share
3 answers

You can use itertools.groupbyto group by the same IP addresses:

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'}

, , dict , , IP.

+7

- , 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__ , a __repr__, .


, , Jon Clements. .

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

.

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

@Ignacio Vazquez-Abrams @M.T. .

0

Source: https://habr.com/ru/post/1649028/


All Articles