1

I need to store list of objects whose number of keys are not fixed in CSV file.

Example :

suppose I have a object

obj1 = { "name": "abc", "class" : "10th" }

obje2 = { "name": "abcd", "class" : "11th", "div" : "A" }

So There will be common elements, but I need to store all the elements

My output would be like this :

enter image description here

Monika
  • 195
  • 1
  • 1
  • 10
  • What did you try? Did you have a look at https://docs.python.org/3/library/csv.html ? If the output is not as expected, you could use https://docs.python.org/3/library/collections.html#collections.defaultdict to return `None` as value for missing keys in your dictionaries. – Jonathan Scholbach Sep 23 '21 at 09:18
  • https://stackoverflow.com/a/5946463/10342778 – Ahmad Anis Sep 23 '21 at 09:18

2 Answers2

2

Sure thing. You'll just have to gather up all of the keys first – that's done with set unions – and then feed the data to a csv.DictWriter.

import csv
import sys

data = [
    {"name": "abc", "class": "10th"},
    {"name": "abcd", "class": "11th", "div": "A"},
    {"name": "qweabcd", "class": "11th", "diy": "Q"},
]

all_keys = set()
for obj in data:
    all_keys |= set(obj)

writer = csv.DictWriter(sys.stdout, sorted(all_keys))
writer.writeheader()
for obj in data:
    writer.writerow(obj)

This outputs

class,div,diy,name
10th,,,abc
11th,A,,abcd
11th,,Q,qweabcd

Since sets don't have an intrinsic order, I'm using sorted to sort the keys alphabetically.

If you need a specific order, that can be done with a custom key function to sorted.

key_order = ["name", "class"]


def get_key_sort_value(key):
    if key in key_order:
        return (0, key_order.index(key))
    return (1, key)


writer = csv.DictWriter(sys.stdout, sorted(all_keys, key=get_key_sort_value))

# ...

will sort name and class first, followed by other keys in alphabetical order.

AKX
  • 152,115
  • 15
  • 115
  • 172
1

Another solution, with pandas:

import pandas as pd

obj1 = {"name": "abc", "class": "10th"}
obj2 = {"name": "abcd", "class": "11th", "div": "A"}

df = pd.DataFrame([obj1, obj2])
print(df)
df.to_csv("data.csv", index=False)

Prints:

   name class  div
0   abc  10th  NaN
1  abcd  11th    A

and saves data.csv (screenshot from LibreOffice):

enter image description here

Andrej Kesely
  • 168,389
  • 15
  • 48
  • 91
  • I would imagine this has quite a lot of overhead (especially if you have lots of objects)... – AKX Sep 23 '21 at 09:42