वर्तमान में मैं उस मामले से जूझ रहा हूं जिसमें मुझे शब्दकोशों में शामिल होने की आवश्यकता है, फिर उन्हें अलग-अलग कुंजी द्वारा समूहित करें और अंत में मूल्यों का योग करें। और ईमानदार होने के लिए मुझे अपने शब्दकोशों पर कुछ बार पुनरावृत्ति किए बिना ऐसा करने का प्रभावी तरीका नहीं मिल रहा है। मैं जल्दी से समझाऊंगा कि मेरे कदम कैसे दिखते हैं।

  1. मैं दिए गए संग्रह के लिए मोंगोडब से पूछताछ कर रहा हूं और मैं प्रारूप में शब्दकोशों की सूची लौटा रहा हूं:
# Each document has unique _id

results = [{"_id": "111111111111111111111111", "countryCode": "SG"}, 
{"_id": "111111111111111111111112", "countryCode": "SG"}, 
{"_id": "111111111111111111111113", "countryCode": "CN"}, 
{"_id": "111111111111111111111114", "countryCode": "SG"}, 
{"_id": "111111111111111111111115", "countryCode": "SG"}, 
{"_id": "111111111111111111111116", "countryCode": "DE"}]

मैं इसे पेजिनेशन के साथ कर रहा हूं, इसलिए मैं 1000 दस्तावेज़ों के आकार के आलसी तरीके से क्वेरी से लौट रहा हूं। (दस्तावेजों की सूची)

  1. ऊपर दी गई सूची में से प्रत्येक _id के लिए मैं एकत्रीकरण क्वेरी के साथ एक और संग्रहण पूछता हूं जिसमें मैं मूल रूप से समूह बनाता हूं और मैं दिए गए _id के लिए कुछ आंकड़े गिनता हूं। तो यहाँ मेरी क्वेरी का उदाहरण है:

def query_events(collection_id: str, ids: list):
    q = [
        {"$match": {"recordId": {"$in": ids}}},
        {"$unwind": {...}},
        {"$project": {...}},
        {"$group": {...}},
        {"$group": {...}}
    ]
    coll = db.get_collection(collection_id)
    return list(coll.aggregate(q))
  1. इस प्रश्न के परिणामों के साथ मैं कुछ प्रसंस्करण करता हूं और मैं इसे एक बड़े शब्दकोश में परिवर्तित करता हूं। नीचे की तरह प्रारूप में:

changes = {
"111111111111111111111111": {"ADDED": 15, "MODIFIED" : 12, "REMOVED" : 3}, 
"111111111111111111111112": {"ADDED": 12, "REMOVED" : 12}, 
"111111111111111111111113": {"ADDED": 3, "MODIFIED" : 3, "REMOVED" : 55}, 
"111111111111111111111114": {}, 
"111111111111111111111115": {"ADDED": 10, "MODIFIED" : 15, "REMOVED" : 43}, 
"111111111111111111111116": {"ADDED": 44, "MODIFIED" : 52, "REMOVED" : 11}, 
}

और अब मेरा लक्ष्य इस शब्दकोश (बिंदु 3) को (बिंदु 1) के शब्दकोशों की सूची के साथ इस तरह मिलाना है कि मुझे अपने शब्दकोश (बिंदु 3) में देश के बारे में जानकारी होगी। मैंने कुछ इस तरह की कोशिश की:

for item in results:
    _id = item['_id']
    if _id in changes:
        del item['_id']
        changes[_id].update(item)

उसके बाद मुझे कुछ ऐसा मिलता है:


changes = {
"111111111111111111111111": {"ADDED": 15, "MODIFIED" : 12, "REMOVED" : 3, "countryCode": "SG"}, 
"111111111111111111111112": {"ADDED": 12, "REMOVED" : 12, "countryCode": "SG"}, 
"111111111111111111111113": {"ADDED": 3, "MODIFIED" : 3, "REMOVED" : 55, "countryCode": "CN"}, 
"111111111111111111111114": {"countryCode": "SG"}, 
"111111111111111111111115": {"ADDED": 10, "MODIFIED" : 15, "REMOVED" : 43, "countryCode": "SG"}, 
"111111111111111111111116": {"ADDED": 44, "MODIFIED" : 52, "REMOVED" : 11, "countryCode": "DE"}, 
}


लेकिन अब मुझे अपने अंतिम परिणाम के रूप में जो प्राप्त करने की आवश्यकता है वह एक शब्दकोश या शब्दकोशों की सूची है जहां मेरी कुंजी देश कोड होगी, और मूल्य {'ADDED': <sum>, 'MODIFIED" : <sum>, "REMOVED" : <sum>} के साथ शब्दकोश होगा

जैसे यहाँ:

# as a dict

{
"DE" : {"ADDED" : 44, "MODIFIED" : 52 , "REMOVED" :11},
"SG" : {"ADDED" : 37, "MODIFIED" : 27 , "REMOVED" :58},
"CN" : {"ADDED": 3, 'MODIFIED" : 3, "REMOVED" : 55},
}


अभी के लिए मेरा एकमात्र विचार यह है कि किसी तरह अपने शब्दकोश पर पुनरावृति करें और देश को एक कुंजी के रूप में जोड़ने का प्रयास करें यदि यह मौजूद नहीं है और {"ADDED" : 44, "MODIFIED" : 52 , "REMOVED" :11} इस कुंजी के मूल्य के रूप में है, लेकिन यदि देश पहले से ही मौजूद है तो रिकॉर्ड मानों पर पुनरावृति करें और प्रत्येक श्रेणी के लिए (ADDED, REMOVED, MODIFIED) मानों का योग करें। लेकिन मुझे लगता है कि यह कुशल नहीं हो सकता। मुझे संग्रह से डेटा लेना है जिसमें 10 मिलियन से अधिक रिकॉर्ड हैं, इसलिए यदि मैं उन शब्दकोशों पर पुन: प्रयास करूंगा तो शायद यह बहुत धीमा होगा।

मेरा अपमान (शायद कुशल नहीं):


results = [{"_id": "111111111111111111111111", "countryCode": "SG"}, 
{"_id": "111111111111111111111112", "countryCode": "SG"}, 
{"_id": "111111111111111111111113", "countryCode": "CN"}, 
{"_id": "111111111111111111111114", "countryCode": "SG"}, 
{"_id": "111111111111111111111115", "countryCode": "SG"}, 
{"_id": "111111111111111111111116", "countryCode": "DE"}]

changes = {
"111111111111111111111111": {"ADDED": 15, "MODIFIED" : 12, "REMOVED" : 3}, 
"111111111111111111111112": {"ADDED": 12, "REMOVED" : 12}, 
"111111111111111111111113": {"ADDED": 3, "MODIFIED" : 3, "REMOVED" : 55}, 
"111111111111111111111114": {}, 
"111111111111111111111115": {"ADDED": 10, "MODIFIED" : 15, "REMOVED" : 43}, 
"111111111111111111111116": {"ADDED": 44, "MODIFIED" : 52, "REMOVED" : 11}, 
}

# Update dict with countryCode

for item in results:
    _id = item.pop('_id')
    if _id in changes:
        changes[_id].update(item)


# Now changes looks like:

changes = {
"111111111111111111111111": {"ADDED": 15, "MODIFIED" : 12, "REMOVED" : 3, "countryCode": "SG"}, 
"111111111111111111111112": {"ADDED": 12, "REMOVED" : 12, "countryCode": "SG"}, 
"111111111111111111111113": {"ADDED": 3, "MODIFIED" : 3, "REMOVED" : 55, "countryCode": "CN"}, 
"111111111111111111111114": {"countryCode": "SG"}, 
"111111111111111111111115": {"ADDED": 10, "MODIFIED" : 15, "REMOVED" : 43, "countryCode": "SG"}, 
"111111111111111111111116": {"ADDED": 44, "MODIFIED" : 52, "REMOVED" : 11, "countryCode": "DE"}, 
}


# Last step group data by country and sum-up statistics

final_results = {}

for k, v in changes.items():
    country = v.pop("countryCode", "UNKNOWN")
    if country not in final_results:
        final_results[country] = v
    else:
        for ck, cv in v.items():
            if ck not in final_results[country]:
                final_results[country][ck] = cv
            else:
                final_results[country][ck] += cv


# After this for loop I achieved my results:

final_results = {
"DE" : {"ADDED" : 44, "MODIFIED" : 52 , "REMOVED" :11},
"SG" : {"ADDED" : 37, "MODIFIED" : 27 , "REMOVED" :58},
"CN" : {"ADDED": 3, 'MODIFIED" : 3, "REMOVED" : 55},
}


यहां तक ​​​​कि अगर मैंने अपने परिणाम हासिल कर लिए हैं, तो शायद ऐसा करने का बेहतर तरीका है।

क्या आपको पता है कि मैं अपने लक्ष्य को कैसे प्राप्त कर सकता हूं - प्रत्येक एक श्रेणी (ADDED, REMOVED, MODIFIED) के लिए देश स्तर पर समेकित मूल्य प्राप्त करना?

धन्यवाद!

1
Jakub Pluta 24 जुलाई 2021, 12:18
Stack Overflow. में आपका स्वागत है। कृपया ध्यान रखें कि यह कोड-लेखन या शिक्षण सेवा नहीं है। हम विशिष्ट, तकनीकी समस्याओं को हल करने में मदद कर सकते हैं, कोड या सलाह के लिए ओपन-एंडेड अनुरोध नहीं। आपने अब तक क्या प्रयास किया है, और आपको किस विशिष्ट समस्या के लिए सहायता की आवश्यकता है, यह दिखाने के लिए कृपया अपना प्रश्न संपादित करें। कैसे करें, इस पर विवरण के लिए How to Ask a Good Question पेज देखें। सबसे अच्छी मदद हमें आपकी मदद करें।
 – 
itprorh66
24 जुलाई 2021, 19:57

1 उत्तर

सबसे बढ़िया उत्तर

आप itertools.groupby + functools.reduce + collections.Counter + operator.add:

  1. आवश्यक पुस्तकालय आयात करें:
from functools import reduce
from collections import Counter
import operator as op
import itertools as it
  1. हम results सूची की संरचना को बदलने जा रहे हैं, जिसकी कुंजी _id है
results = [{r['_id']: {'countryCode': value} for value in r.values()} for r in results]
  1. फिर, हम changes शब्दकोश को results सूची के साथ अपडेट करने जा रहे हैं।
for index, key in enumerate(changes.keys()):
    changes[key].update(results[index][key])
  1. अंत में, हम अपने डेटा को countryCode कुंजी के आधार पर समूहीकृत करने के लिए itertools.groupby का उपयोग करने जा रहे हैं। aggregations Counters की एक सूची है, उदाहरण के लिए: [Counter({'ADDED': 3, 'MODIFIED': 3, 'REMOVED': 1, 'countryCode': 'DE'}), Counter(...)]। हम उपरोक्त सूची में प्रत्येक काउंटर ऑब्जेक्ट को जोड़ने के लिए reduce का उपयोग करने जा रहे हैं।
output = dict()
for g, iter in it.groupby(changes.values(), lambda d: d['countryCode']):
  aggregations = [Counter(i) for i in iter]
  for agg in aggregations:
    del agg['countryCode']
  aggregations = reduce(op.add, aggregations)
  output[g] = aggregations if g not in output.keys() else reduce(op.add, [output[g], aggregations])

# If you don't make this, then you'll get {'CN': Counter({...}), ...}
output = {key: dict(value) for key, value in output.items()}

आउटपुट:

{'CN': {'ADDED': 3, 'MODIFIED': 3, 'REMOVED': 55},
 'DE': {'ADDED': 44, 'MODIFIED': 52, 'REMOVED': 11},
 'SG': {'ADDED': 37, 'MODIFIED': 27, 'REMOVED': 58}}
1
Carmoreno 26 जुलाई 2021, 15:32