Hello! From the database I get a tuple from it I convert to dict and then to json. But there is data with the same values ​​only different IP they need to be combined into one. Example:

{'is_blocked': 0L, 'ip': '10.10.10.1', 'id': 113L} {'is_blocked': 0L, 'ip': '10.10.10.16', 'id': 113L} 

Need to get:

 {'is_blocked': 0L, 'ip': '10.10.10.1,10.10.10.16', 'id': 113L} 

Question in what sequence to collect dict. Initially not changeable types tuple.

  • Except ip, the rest of the pairs must match (1) Are these pairs always two? (2) - alexlz
  • The remaining pairs are combined. - avdoshkin

3 answers 3

Another option:

 a=({'is_blocked': 0L, 'ip': '10.10.10.1', 'id': 113L} ,{'is_blocked': 0L, 'ip': '10.10.10.16', 'id': 113L}) r = {} for d in a: if d['id'] in r: r[d['id']]['ip'].add(d['ip']) else : r[d['id']] = {'is_blocked':d['is_blocked'], 'ip':set((d['ip'],))} r1 = [] for idfield in r: tmp = r[idfield] r1.append({'id':idfield, 'ip':(','.join(tuple(tmp['ip']))), 'is_blocked':tmp['is_blocked']}) print r1 
     def f(arr): vals, ips, res=[], [], [] for i in arr: ip= i['ip'] i2=i.copy() del i2['ip'] try: ips[vals.index(i2)]+= ","+ip except: vals.append(i2) ips.append(ip) for i in range(len(vals)): vals[i]['ip']=ips[i] res.append(vals[i]) return res 

    Result on ideone
    PS If the source array arr is not planned to be used further in the code, but it will work only with the converted array, then you can slightly improve the code efficiency by removing all references to i2 replacing them with i , and i2=i.copy() erase the line.

      You can give birth to such a function:

       from itertools import groupby from collections import defaultdict def group_dicts(data, key_name, joiner=None): """ Groups an iterable of dictionaries on given key. Non-duplicate elements are joined using joiner function. The default implementation uses ",".join(sorted(item_set)), so beware that a TypeError exception may arise on non-string values. Pass an identity function (lambda x: x) to use sets and stay safe. >>> list(group_dicts([ ... {'id': 113, 'ip': '10.10.10.1', 'is_blocked': 0}, ... {'id': 114, 'ip': '10.10.10.2', 'is_blocked': 1}, ... {'id': 113, 'ip': '10.10.10.16', 'is_blocked': 0} ... ], 'ip')) [{'id': 113, 'ip': '10.10.10.1,10.10.10.16', 'is_blocked': 0}, {'id': 114, 'ip': '10.10.10.2', 'is_blocked': 1}] """ if joiner is None: joiner = lambda items: ",".join(sorted(items)) keyfunc = lambda item: item[key_name] for _, items in groupby(sorted(data, key=keyfunc), keyfunc): result = defaultdict(set) for item in items: for k, v in item.items(): result[k].add(v) yield {k: v.pop() if len(v) == 1 else joiner(v) for k, v in result.items()} 

      Test case for use in docstring.

      But it is ugly and somehow even resource intensive. I would look at whether or not to add GROUP BY (and array_agg (PostgreSQL) / GROUP_CONCAT (MySQL, Oracle)) to the SQL query, since on the part of the DB, such an operation is somehow more convenient.

      • Is it possible to integrate in mysql? - avdoshkin
      • And then! :) See the documentation for GROUP_CONCAT , there are examples. - drdaeman
      • Already read :-) from mysql will be more logical. - avdoshkin