Home > OS >  Create sub list from list of dictionary and update values of dictionary
Create sub list from list of dictionary and update values of dictionary

Time:12-12

I have a list of dictionaries:-

test = [{'Sequence': 'A', 'Tag': '20', 'Option': None},
        {'Sequence': 'A', 'Tag': '23', 'Option': None},
        {'Sequence': 'A', 'Tag': '51A', 'Option': None},
        {'Sequence': 'A', 'Tag': '50A', 'Option': 'A'},
        {'Sequence': 'A', 'Tag': '50A', 'Option': 'F'},
        {'Sequence': 'A', 'Tag': '50A', 'Option': 'K'},
        {'Sequence': 'A', 'Tag': '52A', 'Option': 'A'},
        {'Sequence': 'A', 'Tag': '52A', 'Option': 'B'},
        {'Sequence': 'A', 'Tag': '52A', 'Option': 'C'},
        {'Sequence': 'A', 'Tag': '26T', 'Option': None},
        {'Sequence': 'A', 'Tag': '77B', 'Option': None},
        {'Sequence': 'A', 'Tag': '71A', 'Option': None},
        {'Sequence': 'B', 'Tag': '36', 'Option': None},
        {'Sequence': 'B', 'Tag': '21', 'Option': None},
        {'Sequence': 'B', 'Tag': '32B', 'Option': None},
        {'Sequence': 'B', 'Tag': '32B', 'Option': None},
        {'Sequence': 'B', 'Tag': '50A', 'Option': 'A'},
        {'Sequence': 'B', 'Tag': '50A', 'Option': 'F'},
        {'Sequence': 'B', 'Tag': '50A', 'Option': 'K'},
        {'Sequence': 'B', 'Tag': '52A', 'Option': 'A'},
        {'Sequence': 'B', 'Tag': '52A', 'Option': 'B'},
        {'Sequence': 'B', 'Tag': '52A', 'Option': 'C'},
        {'Sequence': 'B', 'Tag': '57A', 'Option': 'A'},
        {'Sequence': 'B', 'Tag': '57A', 'Option': 'C'},
        {'Sequence': 'B', 'Tag': '59A', 'Option': None},
        {'Sequence': 'B', 'Tag': '59A', 'Option': 'A'},
        {'Sequence': 'B', 'Tag': '59A', 'Option': 'F'},
        {'Sequence': 'B', 'Tag': '70', 'Option': None},
        {'Sequence': 'B', 'Tag': '26T', 'Option': None},
        {'Sequence': 'B', 'Tag': '77B', 'Option': None},
        {'Sequence': 'B', 'Tag': '33B', 'Option': None},
        {'Sequence': 'B', 'Tag': '33B', 'Option': None},
        {'Sequence': 'B', 'Tag': '71A', 'Option': None},
        {'Sequence': 'B', 'Tag': '71F', 'Option': None},
        {'Sequence': 'B', 'Tag': '71F', 'Option': None},
        {'Sequence': 'B', 'Tag': '71G', 'Option': None},
        {'Sequence': 'B', 'Tag': '71G', 'Option': None},
        {'Sequence': 'B', 'Tag': '36', 'Option': None},
        {'Sequence': 'C', 'Tag': '32A', 'Option': None},
        {'Sequence': 'C', 'Tag': '32A', 'Option': None},
        {'Sequence': 'C', 'Tag': '32A', 'Option': None},
        {'Sequence': 'C', 'Tag': '19', 'Option': None},
        {'Sequence': 'C', 'Tag': '71G', 'Option': None},
        {'Sequence': 'C', 'Tag': '71G', 'Option': None},
        {'Sequence': 'C', 'Tag': '13C', 'Option': None},
        {'Sequence': 'C', 'Tag': '53A', 'Option': 'A'},
        {'Sequence': 'C', 'Tag': '53A', 'Option': 'C'},
        {'Sequence': 'C', 'Tag': '54A', 'Option': None},
        {'Sequence': 'C', 'Tag': '72', 'Option': None}]

and I am able to create a separate list of dictionaries based on "Sequence" key:

sorted_data = sorted(test, key=itemgetter('Sequence'))

for key, group in itertools.groupby(sorted_data, key=lambda x: x['Sequence']):
    print(key, list(group))

A [{'Sequence': 'A', 'Tag': '20', 'Option': None}, {'Sequence': 'A', 'Tag': '23', 'Option': None}, {'Sequence': 'A', 'Tag': '51A', 'Option': None}, {'Sequence': 'A', 'Tag': '50A', 'Option': 'A'}, {'Sequence': 'A', 'Tag': '50A', 'Option': 'F'}, {'Sequence': 'A', 'Tag': '50A', 'Option': 'K'}, {'Sequence': 'A', 'Tag': '52A', 'Option': 'A'}, {'Sequence': 'A', 'Tag': '52A', 'Option': 'B'}, {'Sequence': 'A', 'Tag': '52A', 'Option': 'C'}, {'Sequence': 'A', 'Tag': '26T', 'Option': None}, {'Sequence': 'A', 'Tag': '77B', 'Option': None}, {'Sequence': 'A', 'Tag': '71A', 'Option': None}]
B [{'Sequence': 'B', 'Tag': '36', 'Option': None}, {'Sequence': 'B', 'Tag': '21', 'Option': None}, {'Sequence': 'B', 'Tag': '32B', 'Option': None}, {'Sequence': 'B', 'Tag': '32B', 'Option': None}, {'Sequence': 'B', 'Tag': '50A', 'Option': 'A'}, {'Sequence': 'B', 'Tag': '50A', 'Option': 'F'}, {'Sequence': 'B', 'Tag': '50A', 'Option': 'K'}, {'Sequence': 'B', 'Tag': '52A', 'Option': 'A'}, {'Sequence': 'B', 'Tag': '52A', 'Option': 'B'}, {'Sequence': 'B', 'Tag': '52A', 'Option': 'C'}, {'Sequence': 'B', 'Tag': '57A', 'Option': 'A'}, {'Sequence': 'B', 'Tag': '57A', 'Option': 'C'}, {'Sequence': 'B', 'Tag': '59A', 'Option': None}, {'Sequence': 'B', 'Tag': '59A', 'Option': 'A'}, {'Sequence': 'B', 'Tag': '59A', 'Option': 'F'}, {'Sequence': 'B', 'Tag': '70', 'Option': None}, {'Sequence': 'B', 'Tag': '26T', 'Option': None}, {'Sequence': 'B', 'Tag': '77B', 'Option': None}, {'Sequence': 'B', 'Tag': '33B', 'Option': None}, {'Sequence': 'B', 'Tag': '33B', 'Option': None}, {'Sequence': 'B', 'Tag': '71A', 'Option': None}, {'Sequence': 'B', 'Tag': '71F', 'Option': None}, {'Sequence': 'B', 'Tag': '71F', 'Option': None}, {'Sequence': 'B', 'Tag': '71G', 'Option': None}, {'Sequence': 'B', 'Tag': '71G', 'Option': None}, {'Sequence': 'B', 'Tag': '36', 'Option': None}]
C [{'Sequence': 'C', 'Tag': '32A', 'Option': None}, {'Sequence': 'C', 'Tag': '32A', 'Option': None}, {'Sequence': 'C', 'Tag': '32A', 'Option': None}, {'Sequence': 'C', 'Tag': '19', 'Option': None}, {'Sequence': 'C', 'Tag': '71G', 'Option': None}, {'Sequence': 'C', 'Tag': '71G', 'Option': None}, {'Sequence': 'C', 'Tag': '13C', 'Option': None}, {'Sequence': 'C', 'Tag': '53A', 'Option': 'A'}, {'Sequence': 'C', 'Tag': '53A', 'Option': 'C'}, {'Sequence': 'C', 'Tag': '54A', 'Option': None}, {'Sequence': 'C', 'Tag': '72', 'Option': None}]

However, while creating the sublists above if there is a duplicate tag present with different options for example tag '52A' in these cases:

        {'Sequence': 'A', 'Tag': '52A', 'Option': 'A'},
        {'Sequence': 'A', 'Tag': '52A', 'Option': 'B'},
        {'Sequence': 'A', 'Tag': '52A', 'Option': 'C'}

I want to randomly select only 1 dictionary and update that dictionary-like below:-

{'Sequence': 'A', 'Tag': '52B', 'Option': 'B'}

Hope I am able to explain the problem. Any help is appreciated or if I need to rethink my approach of breaking down my original list.

CodePudding user response:

One way using random.choice with collections.defaultdict:

from itertools import groupby
from random import choice
from collections import defaultdict

res = defaultdict(list)

for (seq, tag), g in groupby(test, key=lambda x: (x["Sequence"], x["Tag"])):
    res[seq].append(choice(list(g)))

Output:

defaultdict(list,
            {'A': [{'Sequence': 'A', 'Tag': '20', 'Option': None},
              {'Sequence': 'A', 'Tag': '23', 'Option': None},
              {'Sequence': 'A', 'Tag': '51A', 'Option': None},
              {'Sequence': 'A', 'Tag': '50A', 'Option': 'F'},
              {'Sequence': 'A', 'Tag': '52A', 'Option': 'B'},
              {'Sequence': 'A', 'Tag': '26T', 'Option': None},
              {'Sequence': 'A', 'Tag': '77B', 'Option': None},
              {'Sequence': 'A', 'Tag': '71A', 'Option': None}],
             'B': [{'Sequence': 'B', 'Tag': '36', 'Option': None},
              {'Sequence': 'B', 'Tag': '21', 'Option': None},
              {'Sequence': 'B', 'Tag': '32B', 'Option': None},
              {'Sequence': 'B', 'Tag': '50A', 'Option': 'A'},
              {'Sequence': 'B', 'Tag': '52A', 'Option': 'C'},
              {'Sequence': 'B', 'Tag': '57A', 'Option': 'C'},
              {'Sequence': 'B', 'Tag': '59A', 'Option': 'A'},
              {'Sequence': 'B', 'Tag': '70', 'Option': None},
              {'Sequence': 'B', 'Tag': '26T', 'Option': None},
              {'Sequence': 'B', 'Tag': '77B', 'Option': None},
              {'Sequence': 'B', 'Tag': '33B', 'Option': None},
              {'Sequence': 'B', 'Tag': '71A', 'Option': None},
              {'Sequence': 'B', 'Tag': '71F', 'Option': None},
              {'Sequence': 'B', 'Tag': '71G', 'Option': None},
              {'Sequence': 'B', 'Tag': '36', 'Option': None}],
             'C': [{'Sequence': 'C', 'Tag': '32A', 'Option': None},
              {'Sequence': 'C', 'Tag': '19', 'Option': None},
              {'Sequence': 'C', 'Tag': '71G', 'Option': None},
              {'Sequence': 'C', 'Tag': '13C', 'Option': None},
              {'Sequence': 'C', 'Tag': '53A', 'Option': 'C'},
              {'Sequence': 'C', 'Tag': '54A', 'Option': None},
              {'Sequence': 'C', 'Tag': '72', 'Option': None}]})

Insight:

choice(list(g)) will always return single item, so if there's duplicated tags, it does the random selection, and otherwise, return as it is (since no duplicate means single item).

CodePudding user response:

You can groupby on Sequence and Tag, and using random.choice select one item from each group. Then rearrange the dictionary again to drop Tag from each key and create a dictionary of Sequence keys.

from operator import itemgetter
from itertools import groupby
from random import choice
sorted_data = sorted(test, key=itemgetter('Sequence','Tag'))
out = {}
for key, group in groupby(sorted_data, key=itemgetter('Sequence','Tag')):
    out.setdefault(key[0],[]).append(choice(list(group)))

Sample output:

{'A': [{'Sequence': 'A', 'Tag': '20', 'Option': None},
  {'Sequence': 'A', 'Tag': '23', 'Option': None},
  {'Sequence': 'A', 'Tag': '51A', 'Option': None},
  {'Sequence': 'A', 'Tag': '50A', 'Option': 'A'},
  {'Sequence': 'A', 'Tag': '52A', 'Option': 'A'},
  {'Sequence': 'A', 'Tag': '26T', 'Option': None},
  {'Sequence': 'A', 'Tag': '77B', 'Option': None},
  {'Sequence': 'A', 'Tag': '71A', 'Option': None}],
 'B': [{'Sequence': 'B', 'Tag': '36', 'Option': None},
  {'Sequence': 'B', 'Tag': '21', 'Option': None},
  {'Sequence': 'B', 'Tag': '32B', 'Option': None},
  {'Sequence': 'B', 'Tag': '50A', 'Option': 'K'},
  {'Sequence': 'B', 'Tag': '52A', 'Option': 'C'},
  {'Sequence': 'B', 'Tag': '57A', 'Option': 'C'},
  {'Sequence': 'B', 'Tag': '59A', 'Option': 'A'},
  {'Sequence': 'B', 'Tag': '70', 'Option': None},
  {'Sequence': 'B', 'Tag': '26T', 'Option': None},
  {'Sequence': 'B', 'Tag': '77B', 'Option': None},
  {'Sequence': 'B', 'Tag': '33B', 'Option': None},
  {'Sequence': 'B', 'Tag': '71A', 'Option': None},
  {'Sequence': 'B', 'Tag': '71F', 'Option': None},
  {'Sequence': 'B', 'Tag': '71G', 'Option': None}],
 'C': [{'Sequence': 'C', 'Tag': '32A', 'Option': None},
  {'Sequence': 'C', 'Tag': '19', 'Option': None},
  {'Sequence': 'C', 'Tag': '71G', 'Option': None},
  {'Sequence': 'C', 'Tag': '13C', 'Option': None},
  {'Sequence': 'C', 'Tag': '53A', 'Option': 'A'},
  {'Sequence': 'C', 'Tag': '54A', 'Option': None},
  {'Sequence': 'C', 'Tag': '72', 'Option': None}]}
  • Related