Group by keys and create a list of respective values

Viewed 119

I want to convert my dictionary to this format. I have tried using groupby but not able to achieve the expected format.

input = [
         {'algorithms': 'BLOWFISH', 'dcount': 5.8984375},
         {'algorithms': 'AES-256', 'dcount': 5.609375},
         {'algorithms': 'AES-256', 'dcount': 9.309375},
         {'algorithms': 'RSA', 'dcount': 8.309375},
         {'algorithms': 'BLOWFISH','dcount': 6.309375}
        ]

Expected output:

  output = [
  {
    name: "BLOWFISH",
    data: [5.8984375,6.309375]
  },
  {
    name: "AES-256",
    data: [5.609375,9.309375]
  },
  {
    name: 'RSA',
    data: [8.309375]
  }
]
3 Answers

You need to sort input before itertools.groupby will work:

The operation of groupby() is similar to the uniq filter in Unix. It generates a break or new group every time the value of the key function changes (which is why it is usually necessary to have sorted the data using the same key function). That behavior differs from SQL’s GROUP BY which aggregates common elements regardless of their input order.

from itertools import groupby
import json

input = [
   {
        "algorithms": "BLOWFISH",
        "dcount": 5.8984375
   },
   {
        "algorithms": "AES-256",
        "dcount": 5.609375
   },
   {
        "algorithms": "AES-256",
        "dcount": 9.309375
   },
   {
        "algorithms": "RSA",
        "dcount": 8.309375
   },
   {
        "algorithms": "BLOWFISH",
        "dcount": 6.309375
   }
]

output = [
    {
        "name": k,
        "data": [d["dcount"] for d in g]
    } 
    for k, g in groupby(sorted(input, key=lambda d: d["algorithms"]),
                        key=lambda d: d["algorithms"])
]

print(json.dumps(output, indent=4))

Output:

[
    {
        "name": "AES-256",
        "data": [
            5.609375,
            9.309375
        ]
    },
    {
        "name": "BLOWFISH",
        "data": [
            5.8984375,
            6.309375
        ]
    },
    {
        "name": "RSA",
        "data": [
            8.309375
        ]
    }
]

Had a go at this for you:

data = [
         {'algorithms': 'BLOWFISH', 'dcount': 5.8984375},
         {'algorithms': 'AES-256', 'dcount': 5.609375},
         {'algorithms': 'AES-256', 'dcount': 9.309375},
         {'algorithms': 'RSA', 'dcount': 8.309375},
         {'algorithms': 'BLOWFISH', 'dcount': 6.309375}
        ]

series = []
firstRun = True

for i in data:
    found = False
    if firstRun:
        series.append(
            {
                'name': i['algorithms'],
                'data': [i['dcount']]
            }
        )
        firstRun = False
    else:
        for j in series:
            if i['algorithms'] == j['name']:
                j['data'].append(i['dcount'])
                found = True
            else:
                continue
        if not found:
            series.append(
                {
                    'name': i['algorithms'],
                    'data': [i['dcount']]
                }
            )

This should give you your desired output:

>>> print(series)
[{'name': 'BLOWFISH', 'data': [5.8984375, 6.309375]}, {'name': 'AES-256', 'data': [5.609375, 9.309375]}, {'name': 'RSA', 'data': [8.309375]}]

You can do that with no additional module:

def group_algorithms(input_list):
    out = []
    names = []
    for algorithms in input_list:
        if algorithms['algorithms'] in names:
            out[names.index(algorithms['algorithms'])]["data"].append(algorithms['dcount'])
        else:
            out.append({"name": algorithms['algorithms'],
                        "data": [algorithms['dcount']]})
            names.append(algorithms['algorithms'])
    return out
Related