Vishal Kamlapure
Vishal Kamlapure

Reputation: 590

Group by keys and create a list of respective values

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

Upvotes: 2

Views: 1042

Answers (3)

André Ginklings
André Ginklings

Reputation: 381

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

Upvotes: 0

Miles B
Miles B

Reputation: 129

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

Upvotes: 0

Sash Sinha
Sash Sinha

Reputation: 22350

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

Upvotes: 2

Related Questions