Group and aggregate a list of dictionaries by multiple keys












9















I have a list that includes dictionaries (List[Dict, Dict, ...]) , I would like to uniqify the list based on two keys, but I want to retain the value of another key in the dictionary to make sure I do not lose it by making a list in the key I want to retain. I am using Python for the code. If it is of any significance Python 3.x to be exact.



Let's assume I have the following list of dictionaries with three keys: number, favorite, and color. I want to uniqify the list elements using the keys number and favorite. However for the dictionaries that have the same values number and favorite, I'd like to add a list under the key color to make sure I have all the colors for the same combination of number and favorite. This list should also be unique since it shouldn't need the repeated colors for the same combination. However, if there is only one element for the key color in the final result, it should be a string and not a list.



lst = [
{'number': 1, 'favorite': False, 'color': 'red'},
{'number': 1, 'favorite': False, 'color': 'green'},
{'number': 1, 'favorite': False, 'color': 'red'},
{'number': 1, 'favorite': True, 'color': 'red'},
{'number': 2, 'favorite': False, 'color': 'red'}]


Using the aforementioned uniqify, I would get the following result:



lst = [
{'number': 1, 'favorite': False, 'color': {'red', 'green'}},
{'number': 1, 'favorite': True, 'color': 'red'},
{'number': 2, 'favorite': False, 'color': 'red'},
]


Note that there is only one instance of red where the number is 1 and favorite is False even though it appeared twice in the list before it was uniqified. Also note that when there is only one element for the key color in the second dict, it is a string and not a list.










share|improve this question

























  • Are you interested in using pandas for this?

    – coldspeed
    3 hours ago











  • {'red', 'green'} This still doesn't make any sense.

    – Praind
    3 hours ago











  • it basically is a list that serves as a value to the key color @Praind

    – KaanTheGuru
    3 hours ago











  • Is it necessary to have a string instead of a list if there's only one element?

    – Praind
    3 hours ago











  • yes it is necessary, will edit question to include that detail. Thank you @Praind

    – KaanTheGuru
    3 hours ago
















9















I have a list that includes dictionaries (List[Dict, Dict, ...]) , I would like to uniqify the list based on two keys, but I want to retain the value of another key in the dictionary to make sure I do not lose it by making a list in the key I want to retain. I am using Python for the code. If it is of any significance Python 3.x to be exact.



Let's assume I have the following list of dictionaries with three keys: number, favorite, and color. I want to uniqify the list elements using the keys number and favorite. However for the dictionaries that have the same values number and favorite, I'd like to add a list under the key color to make sure I have all the colors for the same combination of number and favorite. This list should also be unique since it shouldn't need the repeated colors for the same combination. However, if there is only one element for the key color in the final result, it should be a string and not a list.



lst = [
{'number': 1, 'favorite': False, 'color': 'red'},
{'number': 1, 'favorite': False, 'color': 'green'},
{'number': 1, 'favorite': False, 'color': 'red'},
{'number': 1, 'favorite': True, 'color': 'red'},
{'number': 2, 'favorite': False, 'color': 'red'}]


Using the aforementioned uniqify, I would get the following result:



lst = [
{'number': 1, 'favorite': False, 'color': {'red', 'green'}},
{'number': 1, 'favorite': True, 'color': 'red'},
{'number': 2, 'favorite': False, 'color': 'red'},
]


Note that there is only one instance of red where the number is 1 and favorite is False even though it appeared twice in the list before it was uniqified. Also note that when there is only one element for the key color in the second dict, it is a string and not a list.










share|improve this question

























  • Are you interested in using pandas for this?

    – coldspeed
    3 hours ago











  • {'red', 'green'} This still doesn't make any sense.

    – Praind
    3 hours ago











  • it basically is a list that serves as a value to the key color @Praind

    – KaanTheGuru
    3 hours ago











  • Is it necessary to have a string instead of a list if there's only one element?

    – Praind
    3 hours ago











  • yes it is necessary, will edit question to include that detail. Thank you @Praind

    – KaanTheGuru
    3 hours ago














9












9








9








I have a list that includes dictionaries (List[Dict, Dict, ...]) , I would like to uniqify the list based on two keys, but I want to retain the value of another key in the dictionary to make sure I do not lose it by making a list in the key I want to retain. I am using Python for the code. If it is of any significance Python 3.x to be exact.



Let's assume I have the following list of dictionaries with three keys: number, favorite, and color. I want to uniqify the list elements using the keys number and favorite. However for the dictionaries that have the same values number and favorite, I'd like to add a list under the key color to make sure I have all the colors for the same combination of number and favorite. This list should also be unique since it shouldn't need the repeated colors for the same combination. However, if there is only one element for the key color in the final result, it should be a string and not a list.



lst = [
{'number': 1, 'favorite': False, 'color': 'red'},
{'number': 1, 'favorite': False, 'color': 'green'},
{'number': 1, 'favorite': False, 'color': 'red'},
{'number': 1, 'favorite': True, 'color': 'red'},
{'number': 2, 'favorite': False, 'color': 'red'}]


Using the aforementioned uniqify, I would get the following result:



lst = [
{'number': 1, 'favorite': False, 'color': {'red', 'green'}},
{'number': 1, 'favorite': True, 'color': 'red'},
{'number': 2, 'favorite': False, 'color': 'red'},
]


Note that there is only one instance of red where the number is 1 and favorite is False even though it appeared twice in the list before it was uniqified. Also note that when there is only one element for the key color in the second dict, it is a string and not a list.










share|improve this question
















I have a list that includes dictionaries (List[Dict, Dict, ...]) , I would like to uniqify the list based on two keys, but I want to retain the value of another key in the dictionary to make sure I do not lose it by making a list in the key I want to retain. I am using Python for the code. If it is of any significance Python 3.x to be exact.



Let's assume I have the following list of dictionaries with three keys: number, favorite, and color. I want to uniqify the list elements using the keys number and favorite. However for the dictionaries that have the same values number and favorite, I'd like to add a list under the key color to make sure I have all the colors for the same combination of number and favorite. This list should also be unique since it shouldn't need the repeated colors for the same combination. However, if there is only one element for the key color in the final result, it should be a string and not a list.



lst = [
{'number': 1, 'favorite': False, 'color': 'red'},
{'number': 1, 'favorite': False, 'color': 'green'},
{'number': 1, 'favorite': False, 'color': 'red'},
{'number': 1, 'favorite': True, 'color': 'red'},
{'number': 2, 'favorite': False, 'color': 'red'}]


Using the aforementioned uniqify, I would get the following result:



lst = [
{'number': 1, 'favorite': False, 'color': {'red', 'green'}},
{'number': 1, 'favorite': True, 'color': 'red'},
{'number': 2, 'favorite': False, 'color': 'red'},
]


Note that there is only one instance of red where the number is 1 and favorite is False even though it appeared twice in the list before it was uniqified. Also note that when there is only one element for the key color in the second dict, it is a string and not a list.







python python-3.x list dictionary unique






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 47 mins ago









coldspeed

125k22125209




125k22125209










asked 3 hours ago









KaanTheGuruKaanTheGuru

607




607













  • Are you interested in using pandas for this?

    – coldspeed
    3 hours ago











  • {'red', 'green'} This still doesn't make any sense.

    – Praind
    3 hours ago











  • it basically is a list that serves as a value to the key color @Praind

    – KaanTheGuru
    3 hours ago











  • Is it necessary to have a string instead of a list if there's only one element?

    – Praind
    3 hours ago











  • yes it is necessary, will edit question to include that detail. Thank you @Praind

    – KaanTheGuru
    3 hours ago



















  • Are you interested in using pandas for this?

    – coldspeed
    3 hours ago











  • {'red', 'green'} This still doesn't make any sense.

    – Praind
    3 hours ago











  • it basically is a list that serves as a value to the key color @Praind

    – KaanTheGuru
    3 hours ago











  • Is it necessary to have a string instead of a list if there's only one element?

    – Praind
    3 hours ago











  • yes it is necessary, will edit question to include that detail. Thank you @Praind

    – KaanTheGuru
    3 hours ago

















Are you interested in using pandas for this?

– coldspeed
3 hours ago





Are you interested in using pandas for this?

– coldspeed
3 hours ago













{'red', 'green'} This still doesn't make any sense.

– Praind
3 hours ago





{'red', 'green'} This still doesn't make any sense.

– Praind
3 hours ago













it basically is a list that serves as a value to the key color @Praind

– KaanTheGuru
3 hours ago





it basically is a list that serves as a value to the key color @Praind

– KaanTheGuru
3 hours ago













Is it necessary to have a string instead of a list if there's only one element?

– Praind
3 hours ago





Is it necessary to have a string instead of a list if there's only one element?

– Praind
3 hours ago













yes it is necessary, will edit question to include that detail. Thank you @Praind

– KaanTheGuru
3 hours ago





yes it is necessary, will edit question to include that detail. Thank you @Praind

– KaanTheGuru
3 hours ago












4 Answers
4






active

oldest

votes


















9














Using pure python, you can do insert into an OrderedDict to retain insertion order:



from collections import OrderedDict

d = OrderedDict()
for l in lst:
d.setdefault((l['number'], l['favorite']), set()).add(l['color'])

[{'number': k[0], 'favorite': k[1], 'color': v.pop() if len(v) == 1 else v}
for k, v in d.items()]
# [{'color': {'green', 'red'}, 'favorite': False, 'number': 1},
# {'color': 'red', 'favorite': True, 'number': 1},
# {'color': 'red', 'favorite': False, 'number': 2}]




This can also be done quite easily using the pandas GroupBy API:



import pandas as pd

d = (pd.DataFrame(lst)
.groupby(['number', 'favorite'])
.color
.agg(set)
.reset_index()
.to_dict('r'))
d
# [{'color': {'green', 'red'}, 'favorite': False, 'number': 1},
# {'color': {'red'}, 'favorite': True, 'number': 1},
# {'color': {'red'}, 'favorite': False, 'number': 2}]


If the condition of a string for a single element is required, you can use



[{'color': (lambda v: v.pop() if len(v) == 1 else v)(d_.pop('color')), **d_} 
for d_ in d]
# [{'color': {'green', 'red'}, 'favorite': False, 'number': 1},
# {'color': 'red', 'favorite': True, 'number': 1},
# {'color': 'red', 'favorite': False, 'number': 2}]





share|improve this answer

































    2














    A solution in pure Python would be to use a defaultdict with a composite key. You could use that to merge your values.
    Afterwards you can create a list again out of that dictionary.



    from collections import defaultdict

    dct = defaultdict()

    for entry in lst:
    dct[(entry['number'], entry['favorite'])].append(entry['color'])

    lst = [{'number': key[0], 'favorite': key[1], color: value if len(value) > 1 else value[0]}
    for key, value in dct.items()]





    share|improve this answer


























    • *composite key i guess?

      – Vineeth Sai
      3 hours ago











    • @Vineeth Sai Indeed ;)

      – Praind
      3 hours ago











    • would this work even if there are more keys than the three mentioned, i.ei if you have a new key? @Praind

      – KaanTheGuru
      3 hours ago








    • 1





      Of course, you just have to add them to the composite key. E.g. dct[(entry['number'], entry['favorite'], entry['otherKey'])].append(entry['color'])

      – Praind
      3 hours ago











    • This would not retain order (unless python3.6), as the question seems to require.

      – coldspeed
      45 mins ago





















    2














    Or groupby of itertools:



    import itertools
    lst = [
    {'number': 1, 'favorite': False, 'color': 'red'},
    {'number': 1, 'favorite': False, 'color': 'green'},
    {'number': 1, 'favorite': False, 'color': 'red'},
    {'number': 1, 'favorite': True, 'color': 'red'},
    {'number': 2, 'favorite': False, 'color': 'red'}]
    l=[list(y) for x,y in itertools.groupby(sorted(lst,key=lambda x: (x['number'],x['favorite'])),lambda x: (x['number'],x['favorite']))]
    print([{k:(v if k!='color' else list(set([x['color'] for x in i]))) for k,v in i[0].items()} for i in l])


    Output:



    [{'number': 1, 'favorite': False, 'color': ['green', 'red']}, {'number': 1, 'favorite': True, 'color': ['red']}, {'number': 2, 'favorite': False, 'color': ['red']}]





    share|improve this answer





















    • 1





      Do you know that your solution won't work if the input list isn't already sorted (w.r.t. number and favorite)? Like if the list contained first dict element as number=1, and favorite=False, second as number=1, and favorite=True, and then number=1, and favorite=False.

      – Muhammad Ahmad
      2 hours ago






    • 1





      Try with this input list: lst = [ {'number': 1, 'favorite': False, 'color': 'red'}, {'number': 1, 'favorite': True, 'color': 'red'}, {'number': 1, 'favorite': False, 'color': 'green'}, {'number': 1, 'favorite': False, 'color': 'red'}, {'number': 2, 'favorite': False, 'color': 'red'}]

      – Muhammad Ahmad
      2 hours ago











    • @MuhammadAhmad I edited my answer, sorry.

      – U9-Forward
      2 hours ago



















    0














    Here's one way to do it,



    I've built a dict first using a tuple as a composite key, Then made a new list out of that dict. You can write comprehensions to further reduce lines and optimize it, Hope it helps.



    new_dict = {}

    for item in lst:
    try: # if already exists then append to the list
    new_dict.get((item['number'], item['favorite']))
    new_dict[(item['number'], item['favorite'])].append(item['color'])
    except KeyError: # if it doesn't then create a new entry to that key
    new_dict[(item['number'], item['favorite'])] = [item['color']]


    final_list =
    for k, v in new_dict.items(): # keep appending dicts to our list
    final_list.append({'number': k[0], 'favorite': k[1], 'color':set(v)})

    print(final_list)


    Outputs:



    [{'number': 1, 'favorite': False, 'color': {'green', 'red'}}, {'number': 1, 'favorite': True, 'color': {'red'}}, {'number': 2, 'favorite': False, 'color': {'red'}}]





    share|improve this answer























      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54248936%2fgroup-and-aggregate-a-list-of-dictionaries-by-multiple-keys%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      9














      Using pure python, you can do insert into an OrderedDict to retain insertion order:



      from collections import OrderedDict

      d = OrderedDict()
      for l in lst:
      d.setdefault((l['number'], l['favorite']), set()).add(l['color'])

      [{'number': k[0], 'favorite': k[1], 'color': v.pop() if len(v) == 1 else v}
      for k, v in d.items()]
      # [{'color': {'green', 'red'}, 'favorite': False, 'number': 1},
      # {'color': 'red', 'favorite': True, 'number': 1},
      # {'color': 'red', 'favorite': False, 'number': 2}]




      This can also be done quite easily using the pandas GroupBy API:



      import pandas as pd

      d = (pd.DataFrame(lst)
      .groupby(['number', 'favorite'])
      .color
      .agg(set)
      .reset_index()
      .to_dict('r'))
      d
      # [{'color': {'green', 'red'}, 'favorite': False, 'number': 1},
      # {'color': {'red'}, 'favorite': True, 'number': 1},
      # {'color': {'red'}, 'favorite': False, 'number': 2}]


      If the condition of a string for a single element is required, you can use



      [{'color': (lambda v: v.pop() if len(v) == 1 else v)(d_.pop('color')), **d_} 
      for d_ in d]
      # [{'color': {'green', 'red'}, 'favorite': False, 'number': 1},
      # {'color': 'red', 'favorite': True, 'number': 1},
      # {'color': 'red', 'favorite': False, 'number': 2}]





      share|improve this answer






























        9














        Using pure python, you can do insert into an OrderedDict to retain insertion order:



        from collections import OrderedDict

        d = OrderedDict()
        for l in lst:
        d.setdefault((l['number'], l['favorite']), set()).add(l['color'])

        [{'number': k[0], 'favorite': k[1], 'color': v.pop() if len(v) == 1 else v}
        for k, v in d.items()]
        # [{'color': {'green', 'red'}, 'favorite': False, 'number': 1},
        # {'color': 'red', 'favorite': True, 'number': 1},
        # {'color': 'red', 'favorite': False, 'number': 2}]




        This can also be done quite easily using the pandas GroupBy API:



        import pandas as pd

        d = (pd.DataFrame(lst)
        .groupby(['number', 'favorite'])
        .color
        .agg(set)
        .reset_index()
        .to_dict('r'))
        d
        # [{'color': {'green', 'red'}, 'favorite': False, 'number': 1},
        # {'color': {'red'}, 'favorite': True, 'number': 1},
        # {'color': {'red'}, 'favorite': False, 'number': 2}]


        If the condition of a string for a single element is required, you can use



        [{'color': (lambda v: v.pop() if len(v) == 1 else v)(d_.pop('color')), **d_} 
        for d_ in d]
        # [{'color': {'green', 'red'}, 'favorite': False, 'number': 1},
        # {'color': 'red', 'favorite': True, 'number': 1},
        # {'color': 'red', 'favorite': False, 'number': 2}]





        share|improve this answer




























          9












          9








          9







          Using pure python, you can do insert into an OrderedDict to retain insertion order:



          from collections import OrderedDict

          d = OrderedDict()
          for l in lst:
          d.setdefault((l['number'], l['favorite']), set()).add(l['color'])

          [{'number': k[0], 'favorite': k[1], 'color': v.pop() if len(v) == 1 else v}
          for k, v in d.items()]
          # [{'color': {'green', 'red'}, 'favorite': False, 'number': 1},
          # {'color': 'red', 'favorite': True, 'number': 1},
          # {'color': 'red', 'favorite': False, 'number': 2}]




          This can also be done quite easily using the pandas GroupBy API:



          import pandas as pd

          d = (pd.DataFrame(lst)
          .groupby(['number', 'favorite'])
          .color
          .agg(set)
          .reset_index()
          .to_dict('r'))
          d
          # [{'color': {'green', 'red'}, 'favorite': False, 'number': 1},
          # {'color': {'red'}, 'favorite': True, 'number': 1},
          # {'color': {'red'}, 'favorite': False, 'number': 2}]


          If the condition of a string for a single element is required, you can use



          [{'color': (lambda v: v.pop() if len(v) == 1 else v)(d_.pop('color')), **d_} 
          for d_ in d]
          # [{'color': {'green', 'red'}, 'favorite': False, 'number': 1},
          # {'color': 'red', 'favorite': True, 'number': 1},
          # {'color': 'red', 'favorite': False, 'number': 2}]





          share|improve this answer















          Using pure python, you can do insert into an OrderedDict to retain insertion order:



          from collections import OrderedDict

          d = OrderedDict()
          for l in lst:
          d.setdefault((l['number'], l['favorite']), set()).add(l['color'])

          [{'number': k[0], 'favorite': k[1], 'color': v.pop() if len(v) == 1 else v}
          for k, v in d.items()]
          # [{'color': {'green', 'red'}, 'favorite': False, 'number': 1},
          # {'color': 'red', 'favorite': True, 'number': 1},
          # {'color': 'red', 'favorite': False, 'number': 2}]




          This can also be done quite easily using the pandas GroupBy API:



          import pandas as pd

          d = (pd.DataFrame(lst)
          .groupby(['number', 'favorite'])
          .color
          .agg(set)
          .reset_index()
          .to_dict('r'))
          d
          # [{'color': {'green', 'red'}, 'favorite': False, 'number': 1},
          # {'color': {'red'}, 'favorite': True, 'number': 1},
          # {'color': {'red'}, 'favorite': False, 'number': 2}]


          If the condition of a string for a single element is required, you can use



          [{'color': (lambda v: v.pop() if len(v) == 1 else v)(d_.pop('color')), **d_} 
          for d_ in d]
          # [{'color': {'green', 'red'}, 'favorite': False, 'number': 1},
          # {'color': 'red', 'favorite': True, 'number': 1},
          # {'color': 'red', 'favorite': False, 'number': 2}]






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited 3 hours ago

























          answered 3 hours ago









          coldspeedcoldspeed

          125k22125209




          125k22125209

























              2














              A solution in pure Python would be to use a defaultdict with a composite key. You could use that to merge your values.
              Afterwards you can create a list again out of that dictionary.



              from collections import defaultdict

              dct = defaultdict()

              for entry in lst:
              dct[(entry['number'], entry['favorite'])].append(entry['color'])

              lst = [{'number': key[0], 'favorite': key[1], color: value if len(value) > 1 else value[0]}
              for key, value in dct.items()]





              share|improve this answer


























              • *composite key i guess?

                – Vineeth Sai
                3 hours ago











              • @Vineeth Sai Indeed ;)

                – Praind
                3 hours ago











              • would this work even if there are more keys than the three mentioned, i.ei if you have a new key? @Praind

                – KaanTheGuru
                3 hours ago








              • 1





                Of course, you just have to add them to the composite key. E.g. dct[(entry['number'], entry['favorite'], entry['otherKey'])].append(entry['color'])

                – Praind
                3 hours ago











              • This would not retain order (unless python3.6), as the question seems to require.

                – coldspeed
                45 mins ago


















              2














              A solution in pure Python would be to use a defaultdict with a composite key. You could use that to merge your values.
              Afterwards you can create a list again out of that dictionary.



              from collections import defaultdict

              dct = defaultdict()

              for entry in lst:
              dct[(entry['number'], entry['favorite'])].append(entry['color'])

              lst = [{'number': key[0], 'favorite': key[1], color: value if len(value) > 1 else value[0]}
              for key, value in dct.items()]





              share|improve this answer


























              • *composite key i guess?

                – Vineeth Sai
                3 hours ago











              • @Vineeth Sai Indeed ;)

                – Praind
                3 hours ago











              • would this work even if there are more keys than the three mentioned, i.ei if you have a new key? @Praind

                – KaanTheGuru
                3 hours ago








              • 1





                Of course, you just have to add them to the composite key. E.g. dct[(entry['number'], entry['favorite'], entry['otherKey'])].append(entry['color'])

                – Praind
                3 hours ago











              • This would not retain order (unless python3.6), as the question seems to require.

                – coldspeed
                45 mins ago
















              2












              2








              2







              A solution in pure Python would be to use a defaultdict with a composite key. You could use that to merge your values.
              Afterwards you can create a list again out of that dictionary.



              from collections import defaultdict

              dct = defaultdict()

              for entry in lst:
              dct[(entry['number'], entry['favorite'])].append(entry['color'])

              lst = [{'number': key[0], 'favorite': key[1], color: value if len(value) > 1 else value[0]}
              for key, value in dct.items()]





              share|improve this answer















              A solution in pure Python would be to use a defaultdict with a composite key. You could use that to merge your values.
              Afterwards you can create a list again out of that dictionary.



              from collections import defaultdict

              dct = defaultdict()

              for entry in lst:
              dct[(entry['number'], entry['favorite'])].append(entry['color'])

              lst = [{'number': key[0], 'favorite': key[1], color: value if len(value) > 1 else value[0]}
              for key, value in dct.items()]






              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited 3 hours ago

























              answered 3 hours ago









              PraindPraind

              874718




              874718













              • *composite key i guess?

                – Vineeth Sai
                3 hours ago











              • @Vineeth Sai Indeed ;)

                – Praind
                3 hours ago











              • would this work even if there are more keys than the three mentioned, i.ei if you have a new key? @Praind

                – KaanTheGuru
                3 hours ago








              • 1





                Of course, you just have to add them to the composite key. E.g. dct[(entry['number'], entry['favorite'], entry['otherKey'])].append(entry['color'])

                – Praind
                3 hours ago











              • This would not retain order (unless python3.6), as the question seems to require.

                – coldspeed
                45 mins ago





















              • *composite key i guess?

                – Vineeth Sai
                3 hours ago











              • @Vineeth Sai Indeed ;)

                – Praind
                3 hours ago











              • would this work even if there are more keys than the three mentioned, i.ei if you have a new key? @Praind

                – KaanTheGuru
                3 hours ago








              • 1





                Of course, you just have to add them to the composite key. E.g. dct[(entry['number'], entry['favorite'], entry['otherKey'])].append(entry['color'])

                – Praind
                3 hours ago











              • This would not retain order (unless python3.6), as the question seems to require.

                – coldspeed
                45 mins ago



















              *composite key i guess?

              – Vineeth Sai
              3 hours ago





              *composite key i guess?

              – Vineeth Sai
              3 hours ago













              @Vineeth Sai Indeed ;)

              – Praind
              3 hours ago





              @Vineeth Sai Indeed ;)

              – Praind
              3 hours ago













              would this work even if there are more keys than the three mentioned, i.ei if you have a new key? @Praind

              – KaanTheGuru
              3 hours ago







              would this work even if there are more keys than the three mentioned, i.ei if you have a new key? @Praind

              – KaanTheGuru
              3 hours ago






              1




              1





              Of course, you just have to add them to the composite key. E.g. dct[(entry['number'], entry['favorite'], entry['otherKey'])].append(entry['color'])

              – Praind
              3 hours ago





              Of course, you just have to add them to the composite key. E.g. dct[(entry['number'], entry['favorite'], entry['otherKey'])].append(entry['color'])

              – Praind
              3 hours ago













              This would not retain order (unless python3.6), as the question seems to require.

              – coldspeed
              45 mins ago







              This would not retain order (unless python3.6), as the question seems to require.

              – coldspeed
              45 mins ago













              2














              Or groupby of itertools:



              import itertools
              lst = [
              {'number': 1, 'favorite': False, 'color': 'red'},
              {'number': 1, 'favorite': False, 'color': 'green'},
              {'number': 1, 'favorite': False, 'color': 'red'},
              {'number': 1, 'favorite': True, 'color': 'red'},
              {'number': 2, 'favorite': False, 'color': 'red'}]
              l=[list(y) for x,y in itertools.groupby(sorted(lst,key=lambda x: (x['number'],x['favorite'])),lambda x: (x['number'],x['favorite']))]
              print([{k:(v if k!='color' else list(set([x['color'] for x in i]))) for k,v in i[0].items()} for i in l])


              Output:



              [{'number': 1, 'favorite': False, 'color': ['green', 'red']}, {'number': 1, 'favorite': True, 'color': ['red']}, {'number': 2, 'favorite': False, 'color': ['red']}]





              share|improve this answer





















              • 1





                Do you know that your solution won't work if the input list isn't already sorted (w.r.t. number and favorite)? Like if the list contained first dict element as number=1, and favorite=False, second as number=1, and favorite=True, and then number=1, and favorite=False.

                – Muhammad Ahmad
                2 hours ago






              • 1





                Try with this input list: lst = [ {'number': 1, 'favorite': False, 'color': 'red'}, {'number': 1, 'favorite': True, 'color': 'red'}, {'number': 1, 'favorite': False, 'color': 'green'}, {'number': 1, 'favorite': False, 'color': 'red'}, {'number': 2, 'favorite': False, 'color': 'red'}]

                – Muhammad Ahmad
                2 hours ago











              • @MuhammadAhmad I edited my answer, sorry.

                – U9-Forward
                2 hours ago
















              2














              Or groupby of itertools:



              import itertools
              lst = [
              {'number': 1, 'favorite': False, 'color': 'red'},
              {'number': 1, 'favorite': False, 'color': 'green'},
              {'number': 1, 'favorite': False, 'color': 'red'},
              {'number': 1, 'favorite': True, 'color': 'red'},
              {'number': 2, 'favorite': False, 'color': 'red'}]
              l=[list(y) for x,y in itertools.groupby(sorted(lst,key=lambda x: (x['number'],x['favorite'])),lambda x: (x['number'],x['favorite']))]
              print([{k:(v if k!='color' else list(set([x['color'] for x in i]))) for k,v in i[0].items()} for i in l])


              Output:



              [{'number': 1, 'favorite': False, 'color': ['green', 'red']}, {'number': 1, 'favorite': True, 'color': ['red']}, {'number': 2, 'favorite': False, 'color': ['red']}]





              share|improve this answer





















              • 1





                Do you know that your solution won't work if the input list isn't already sorted (w.r.t. number and favorite)? Like if the list contained first dict element as number=1, and favorite=False, second as number=1, and favorite=True, and then number=1, and favorite=False.

                – Muhammad Ahmad
                2 hours ago






              • 1





                Try with this input list: lst = [ {'number': 1, 'favorite': False, 'color': 'red'}, {'number': 1, 'favorite': True, 'color': 'red'}, {'number': 1, 'favorite': False, 'color': 'green'}, {'number': 1, 'favorite': False, 'color': 'red'}, {'number': 2, 'favorite': False, 'color': 'red'}]

                – Muhammad Ahmad
                2 hours ago











              • @MuhammadAhmad I edited my answer, sorry.

                – U9-Forward
                2 hours ago














              2












              2








              2







              Or groupby of itertools:



              import itertools
              lst = [
              {'number': 1, 'favorite': False, 'color': 'red'},
              {'number': 1, 'favorite': False, 'color': 'green'},
              {'number': 1, 'favorite': False, 'color': 'red'},
              {'number': 1, 'favorite': True, 'color': 'red'},
              {'number': 2, 'favorite': False, 'color': 'red'}]
              l=[list(y) for x,y in itertools.groupby(sorted(lst,key=lambda x: (x['number'],x['favorite'])),lambda x: (x['number'],x['favorite']))]
              print([{k:(v if k!='color' else list(set([x['color'] for x in i]))) for k,v in i[0].items()} for i in l])


              Output:



              [{'number': 1, 'favorite': False, 'color': ['green', 'red']}, {'number': 1, 'favorite': True, 'color': ['red']}, {'number': 2, 'favorite': False, 'color': ['red']}]





              share|improve this answer















              Or groupby of itertools:



              import itertools
              lst = [
              {'number': 1, 'favorite': False, 'color': 'red'},
              {'number': 1, 'favorite': False, 'color': 'green'},
              {'number': 1, 'favorite': False, 'color': 'red'},
              {'number': 1, 'favorite': True, 'color': 'red'},
              {'number': 2, 'favorite': False, 'color': 'red'}]
              l=[list(y) for x,y in itertools.groupby(sorted(lst,key=lambda x: (x['number'],x['favorite'])),lambda x: (x['number'],x['favorite']))]
              print([{k:(v if k!='color' else list(set([x['color'] for x in i]))) for k,v in i[0].items()} for i in l])


              Output:



              [{'number': 1, 'favorite': False, 'color': ['green', 'red']}, {'number': 1, 'favorite': True, 'color': ['red']}, {'number': 2, 'favorite': False, 'color': ['red']}]






              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited 2 hours ago

























              answered 3 hours ago









              U9-ForwardU9-Forward

              14.1k21337




              14.1k21337








              • 1





                Do you know that your solution won't work if the input list isn't already sorted (w.r.t. number and favorite)? Like if the list contained first dict element as number=1, and favorite=False, second as number=1, and favorite=True, and then number=1, and favorite=False.

                – Muhammad Ahmad
                2 hours ago






              • 1





                Try with this input list: lst = [ {'number': 1, 'favorite': False, 'color': 'red'}, {'number': 1, 'favorite': True, 'color': 'red'}, {'number': 1, 'favorite': False, 'color': 'green'}, {'number': 1, 'favorite': False, 'color': 'red'}, {'number': 2, 'favorite': False, 'color': 'red'}]

                – Muhammad Ahmad
                2 hours ago











              • @MuhammadAhmad I edited my answer, sorry.

                – U9-Forward
                2 hours ago














              • 1





                Do you know that your solution won't work if the input list isn't already sorted (w.r.t. number and favorite)? Like if the list contained first dict element as number=1, and favorite=False, second as number=1, and favorite=True, and then number=1, and favorite=False.

                – Muhammad Ahmad
                2 hours ago






              • 1





                Try with this input list: lst = [ {'number': 1, 'favorite': False, 'color': 'red'}, {'number': 1, 'favorite': True, 'color': 'red'}, {'number': 1, 'favorite': False, 'color': 'green'}, {'number': 1, 'favorite': False, 'color': 'red'}, {'number': 2, 'favorite': False, 'color': 'red'}]

                – Muhammad Ahmad
                2 hours ago











              • @MuhammadAhmad I edited my answer, sorry.

                – U9-Forward
                2 hours ago








              1




              1





              Do you know that your solution won't work if the input list isn't already sorted (w.r.t. number and favorite)? Like if the list contained first dict element as number=1, and favorite=False, second as number=1, and favorite=True, and then number=1, and favorite=False.

              – Muhammad Ahmad
              2 hours ago





              Do you know that your solution won't work if the input list isn't already sorted (w.r.t. number and favorite)? Like if the list contained first dict element as number=1, and favorite=False, second as number=1, and favorite=True, and then number=1, and favorite=False.

              – Muhammad Ahmad
              2 hours ago




              1




              1





              Try with this input list: lst = [ {'number': 1, 'favorite': False, 'color': 'red'}, {'number': 1, 'favorite': True, 'color': 'red'}, {'number': 1, 'favorite': False, 'color': 'green'}, {'number': 1, 'favorite': False, 'color': 'red'}, {'number': 2, 'favorite': False, 'color': 'red'}]

              – Muhammad Ahmad
              2 hours ago





              Try with this input list: lst = [ {'number': 1, 'favorite': False, 'color': 'red'}, {'number': 1, 'favorite': True, 'color': 'red'}, {'number': 1, 'favorite': False, 'color': 'green'}, {'number': 1, 'favorite': False, 'color': 'red'}, {'number': 2, 'favorite': False, 'color': 'red'}]

              – Muhammad Ahmad
              2 hours ago













              @MuhammadAhmad I edited my answer, sorry.

              – U9-Forward
              2 hours ago





              @MuhammadAhmad I edited my answer, sorry.

              – U9-Forward
              2 hours ago











              0














              Here's one way to do it,



              I've built a dict first using a tuple as a composite key, Then made a new list out of that dict. You can write comprehensions to further reduce lines and optimize it, Hope it helps.



              new_dict = {}

              for item in lst:
              try: # if already exists then append to the list
              new_dict.get((item['number'], item['favorite']))
              new_dict[(item['number'], item['favorite'])].append(item['color'])
              except KeyError: # if it doesn't then create a new entry to that key
              new_dict[(item['number'], item['favorite'])] = [item['color']]


              final_list =
              for k, v in new_dict.items(): # keep appending dicts to our list
              final_list.append({'number': k[0], 'favorite': k[1], 'color':set(v)})

              print(final_list)


              Outputs:



              [{'number': 1, 'favorite': False, 'color': {'green', 'red'}}, {'number': 1, 'favorite': True, 'color': {'red'}}, {'number': 2, 'favorite': False, 'color': {'red'}}]





              share|improve this answer




























                0














                Here's one way to do it,



                I've built a dict first using a tuple as a composite key, Then made a new list out of that dict. You can write comprehensions to further reduce lines and optimize it, Hope it helps.



                new_dict = {}

                for item in lst:
                try: # if already exists then append to the list
                new_dict.get((item['number'], item['favorite']))
                new_dict[(item['number'], item['favorite'])].append(item['color'])
                except KeyError: # if it doesn't then create a new entry to that key
                new_dict[(item['number'], item['favorite'])] = [item['color']]


                final_list =
                for k, v in new_dict.items(): # keep appending dicts to our list
                final_list.append({'number': k[0], 'favorite': k[1], 'color':set(v)})

                print(final_list)


                Outputs:



                [{'number': 1, 'favorite': False, 'color': {'green', 'red'}}, {'number': 1, 'favorite': True, 'color': {'red'}}, {'number': 2, 'favorite': False, 'color': {'red'}}]





                share|improve this answer


























                  0












                  0








                  0







                  Here's one way to do it,



                  I've built a dict first using a tuple as a composite key, Then made a new list out of that dict. You can write comprehensions to further reduce lines and optimize it, Hope it helps.



                  new_dict = {}

                  for item in lst:
                  try: # if already exists then append to the list
                  new_dict.get((item['number'], item['favorite']))
                  new_dict[(item['number'], item['favorite'])].append(item['color'])
                  except KeyError: # if it doesn't then create a new entry to that key
                  new_dict[(item['number'], item['favorite'])] = [item['color']]


                  final_list =
                  for k, v in new_dict.items(): # keep appending dicts to our list
                  final_list.append({'number': k[0], 'favorite': k[1], 'color':set(v)})

                  print(final_list)


                  Outputs:



                  [{'number': 1, 'favorite': False, 'color': {'green', 'red'}}, {'number': 1, 'favorite': True, 'color': {'red'}}, {'number': 2, 'favorite': False, 'color': {'red'}}]





                  share|improve this answer













                  Here's one way to do it,



                  I've built a dict first using a tuple as a composite key, Then made a new list out of that dict. You can write comprehensions to further reduce lines and optimize it, Hope it helps.



                  new_dict = {}

                  for item in lst:
                  try: # if already exists then append to the list
                  new_dict.get((item['number'], item['favorite']))
                  new_dict[(item['number'], item['favorite'])].append(item['color'])
                  except KeyError: # if it doesn't then create a new entry to that key
                  new_dict[(item['number'], item['favorite'])] = [item['color']]


                  final_list =
                  for k, v in new_dict.items(): # keep appending dicts to our list
                  final_list.append({'number': k[0], 'favorite': k[1], 'color':set(v)})

                  print(final_list)


                  Outputs:



                  [{'number': 1, 'favorite': False, 'color': {'green', 'red'}}, {'number': 1, 'favorite': True, 'color': {'red'}}, {'number': 2, 'favorite': False, 'color': {'red'}}]






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered 3 hours ago









                  Vineeth SaiVineeth Sai

                  2,49051124




                  2,49051124






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54248936%2fgroup-and-aggregate-a-list-of-dictionaries-by-multiple-keys%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Polycentropodidae

                      Magento 2 Error message: Invalid state change requested

                      Paulmy