1
\$\begingroup\$

I'd like to obtain a dict of the following form (not strict):

{65: ['Fresh', 'Frozen'],
 66: ['Fresh', 'Delicatessen'],
 75: ['Grocery', 'Detergents_Paper'],
 128: ['Fresh', 'Delicatessen'],
 154: ['Milk', 'Grocery', 'Delicatessen']}

when I have an input which is list of dicts. Their keys may be intersected and values - not. For example in our case we have the same key 65 in two dicts with value Fresh and Frozen.

This is my solution and I'd like to improve it:

outliers = [
    {65: 'Fresh', 66: 'Fresh', 81: 'Fresh', 95: 'Fresh', 96: 'Fresh',
     128: 'Fresh', 171: 'Fresh', 193: 'Fresh', 218: 'Fresh', 304: 'Fresh',
     305: 'Fresh', 338: 'Fresh', 353: 'Fresh', 355: 'Fresh', 357: 'Fresh',
     412: 'Fresh'},

    {86: 'Milk', 98: 'Milk', 154: 'Milk', 356: 'Milk'},

    {75: 'Grocery', 154: 'Grocery'},

    {38: 'Frozen', 57: 'Frozen', 65: 'Frozen', 145: 'Frozen', 175: 'Frozen',

     264: 'Frozen', 325: 'Frozen', 420: 'Frozen', 429: 'Frozen', 439: 'Frozen'},

    {75: 'Detergents_Paper', 161: 'Detergents_Paper'},

    {66: 'Delicatessen', 109: 'Delicatessen', 128: 'Delicatessen',
     137: 'Delicatessen', 142: 'Delicatessen', 154: 'Delicatessen',
     183: 'Delicatessen', 184: 'Delicatessen', 187: 'Delicatessen',
     203: 'Delicatessen', 233: 'Delicatessen', 285: 'Delicatessen',
     289: 'Delicatessen', 343: 'Delicatessen'}
]

common_outliers = {}
for outlier in outliers:
    for idx, feature in outlier.items():
        if idx not in common_outliers:
            common_outliers[idx] = [feature]
        else:
            common_outliers[idx].append(feature)
common_outliers = {idx: features for idx, features in common_outliers.items()
                   if len(features) > 1}
print(common_outliers)
\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

This implementation is fine. It's easy to read and it works well.

A minor optimization could be to use an auxiliary dictionary to track the keys seen so far, in order to avoid an extra iteration to create the final result. But I don't think this is really important.

seen = {}
common_outliers = {}
for outlier in outliers:
    for idx, feature in outlier.items():
        if idx not in seen:
            seen[idx] = [feature]
        else:
            seen[idx].append(feature)
            common_outliers[idx] = seen[idx]
print(common_outliers)
\$\endgroup\$
1
\$\begingroup\$

Another option is to use Set operations instead of extra dict/list data structures.

output = collections.defaultdict(set)
for idx, o in enumerate(outliers):
    current = set(o.keys())
    for other in outliers[idx+1:]:
        for common_key in current.intersection(other.keys()):
            output[common_key].add(o[common_key])
            output[common_key].add(other[common_key])

The output is a dict of set instead of a dict of list but that is pretty easy to take care of if it is an issue.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.