Group and aggregate a list of dictionaries by multiple keys
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 color
s for the same combination of number
and favorite
. This list should also be unique since it shouldn't need the repeated color
s 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
add a comment |
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 color
s for the same combination of number
and favorite
. This list should also be unique since it shouldn't need the repeated color
s 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
Are you interested in usingpandas
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 keycolor
@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
add a comment |
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 color
s for the same combination of number
and favorite
. This list should also be unique since it shouldn't need the repeated color
s 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
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 color
s for the same combination of number
and favorite
. This list should also be unique since it shouldn't need the repeated color
s 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
python python-3.x list dictionary unique
edited 47 mins ago
coldspeed
125k22125209
125k22125209
asked 3 hours ago
KaanTheGuruKaanTheGuru
607
607
Are you interested in usingpandas
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 keycolor
@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
add a comment |
Are you interested in usingpandas
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 keycolor
@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
add a comment |
4 Answers
4
active
oldest
votes
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}]
add a comment |
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()]
*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
add a comment |
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']}]
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
add a comment |
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'}}]
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e) {
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom)) {
StackExchange.using('gps', function() { StackExchange.gps.track('embedded_signup_form.view', { location: 'question_page' }); });
$window.unbind('scroll', onScroll);
}
};
$window.on('scroll', onScroll);
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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}]
add a comment |
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}]
add a comment |
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}]
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}]
edited 3 hours ago
answered 3 hours ago
coldspeedcoldspeed
125k22125209
125k22125209
add a comment |
add a comment |
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()]
*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
add a comment |
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()]
*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
add a comment |
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()]
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()]
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
add a comment |
*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
add a comment |
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']}]
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
add a comment |
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']}]
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
add a comment |
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']}]
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']}]
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
add a comment |
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
add a comment |
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'}}]
add a comment |
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'}}]
add a comment |
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'}}]
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'}}]
answered 3 hours ago
Vineeth SaiVineeth Sai
2,49051124
2,49051124
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e) {
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom)) {
StackExchange.using('gps', function() { StackExchange.gps.track('embedded_signup_form.view', { location: 'question_page' }); });
$window.unbind('scroll', onScroll);
}
};
$window.on('scroll', onScroll);
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e) {
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom)) {
StackExchange.using('gps', function() { StackExchange.gps.track('embedded_signup_form.view', { location: 'question_page' }); });
$window.unbind('scroll', onScroll);
}
};
$window.on('scroll', onScroll);
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e) {
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom)) {
StackExchange.using('gps', function() { StackExchange.gps.track('embedded_signup_form.view', { location: 'question_page' }); });
$window.unbind('scroll', onScroll);
}
};
$window.on('scroll', onScroll);
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e) {
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom)) {
StackExchange.using('gps', function() { StackExchange.gps.track('embedded_signup_form.view', { location: 'question_page' }); });
$window.unbind('scroll', onScroll);
}
};
$window.on('scroll', onScroll);
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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