पायथन: यदि कोई नया ताना-बाना नहीं है, तो हुकुम की सूची, यदि कोई बड़ा मूल्य है, तो एक वर्धित मूल्य पर मौजूद है


107

मैं ऐसा कुछ करना चाहूंगा।

list_of_urls = ['http://www.google.fr/', 'http://www.google.fr/', 
                'http://www.google.cn/', 'http://www.google.com/', 
                'http://www.google.fr/', 'http://www.google.fr/', 
                'http://www.google.fr/', 'http://www.google.com/', 
                'http://www.google.fr/', 'http://www.google.com/', 
                'http://www.google.cn/']

urls = [{'url': 'http://www.google.fr/', 'nbr': 1}]

for url in list_of_urls:
    if url in [f['url'] for f in urls]:
         urls[??]['nbr'] += 1
    else:
         urls.append({'url': url, 'nbr': 1})

मैं कैसे कर सकता हूँ ? मुझे नहीं पता कि क्या मुझे इसे संपादित करने के लिए टपल लेना चाहिए या टपल इंडेक्स का पता लगाना चाहिए?

कोई मदद ?

जवाबों:


207

यह चीजों को व्यवस्थित करने का एक बहुत ही अजीब तरीका है। यदि आप किसी शब्दकोश में संग्रहीत हैं, तो यह आसान है:

# This example should work in any version of Python.
# urls_d will contain URL keys, with counts as values, like: {'http://www.google.fr/' : 1 }
urls_d = {}
for url in list_of_urls:
    if not url in urls_d:
        urls_d[url] = 1
    else:
        urls_d[url] += 1

पायथन के शब्दकोश को अपडेट करने के लिए यह कोड पाइथन में एक सामान्य "पैटर्न" है। यह इतना सामान्य है कि एक विशेष डेटा संरचना है, defaultdictजो इसे और भी आसान बनाने के लिए बनाई गई है:

from collections import defaultdict  # available in Python 2.5 and newer

urls_d = defaultdict(int)
for url in list_of_urls:
    urls_d[url] += 1

यदि आप defaultdictएक कुंजी का उपयोग करते हैं, और कुंजी पहले से ही नहीं है defaultdict, तो कुंजी स्वतः एक डिफ़ॉल्ट मान के साथ जोड़ दी जाती है। defaultdictप्रतिदेय लेता है आप में पारित कर दिया, और डिफ़ॉल्ट मान प्राप्त करने के लिए यह कहता है। इस मामले में, हम कक्षा में पास हुए int; जब पायथन कॉल करता है तो int()यह शून्य मान देता है। इसलिए, पहली बार जब आप किसी URL का संदर्भ लेते हैं, तो उसकी गणना शून्य से आरंभ की जाती है, और फिर आप एक गणना में जोड़ते हैं।

लेकिन काउंट से भरा एक शब्दकोश भी एक सामान्य पैटर्न है, इसलिए पायथन एक तैयार-से-उपयोग वर्ग प्रदान करता है: containers.Counter आप बस Counterकक्षा को कॉल करके एक उदाहरण बनाते हैं , किसी भी चलने योग्य में गुजरते हुए; यह एक शब्दकोश बनाता है जहाँ कुंजियाँ चलने योग्य से मान हैं, और मान मायने रखता है कि कुंजी कितनी बार पुनरावृति में दिखाई दी। उपरोक्त उदाहरण तब बनता है:

from collections import Counter  # available in Python 2.7 and newer

urls_d = Counter(list_of_urls)

यदि आपको वास्तव में इसे आपके द्वारा दिखाए जाने वाले तरीके से करने की आवश्यकता है, तो सबसे आसान और तेज़ तरीका इन तीन उदाहरणों में से किसी एक का उपयोग करना होगा, और फिर आपको अपनी ज़रूरत का निर्माण करना होगा।

from collections import defaultdict  # available in Python 2.5 and newer

urls_d = defaultdict(int)
for url in list_of_urls:
    urls_d[url] += 1

urls = [{"url": key, "nbr": value} for key, value in urls_d.items()]

यदि आप पायथन 2.7 या नए का उपयोग कर रहे हैं, तो आप इसे एक-लाइनर में कर सकते हैं:

from collections import Counter

urls = [{"url": key, "nbr": value} for key, value in Counter(list_of_urls).items()]

मुझे ऐसा लगता है कि इसे एक django टेम्पलेट में भेजने के लिए मैं ऐसा कर सकता हूं: `urls में u के लिए% {} {{u.url}}: {{u.nbr}} {% endfor%}
Natim

3
आप अभी भी {% url, nbr के लिए urls.items%} {{url}}: {{nbr}} {% endfor%} में कर सकते हैं
stefanw

160

डिफ़ॉल्ट कार्यों का उपयोग करना, लेकिन ऐसा करता है:

urls[url] = urls.get(url, 0) + 1

का उपयोग करते हुए .getयदि यह मौजूद नहीं है, आप एक डिफ़ॉल्ट वापसी प्राप्त कर सकते हैं। डिफ़ॉल्ट रूप से यह कोई भी नहीं है, लेकिन जिस मामले में मैंने आपको भेजा है, वह 0 होगा।


12
वास्तव में मुझे लगता है कि यह सबसे अच्छा जवाब है, क्योंकि यह दिए गए शब्दकोश पर अज्ञेयवादी है, जो एक बहुत बड़ा बोनस है।
बाउंसर

यह एक अच्छा साफ समाधान है।
डायलन हॉग

1
इसका उत्तर होना चाहिए। कुशल, स्वच्छ और बिंदु तक !! मुझे आशा है कि स्टैकओवरफ़्लो समुदाय को प्रश्न पोस्टर के साथ जवाब तय करने की अनुमति देता है।
मवयय १४'१

वास्तव में इस जवाब की तरह काम नहीं कर रहा है अगर कुंजी कोई नहीं ^ ^ या अच्छी तरह से ... कुछ और चरणों की आवश्यकता है ...
सेड्रिक


17

यह मेरे लिए हमेशा ठीक काम करता है:

for url in list_of_urls:
    urls.setdefault(url, 0)
    urls[url] += 1

3

इसे अपने तरीके से करने के लिए? आप इसके लिए ... संरचना का उपयोग कर सकते हैं

for url in list_of_urls:
    for url_dict in urls:
        if url_dict['url'] == url:
            url_dict['nbr'] += 1
            break
    else:
        urls.append(dict(url=url, nbr=1))

लेकिन यह काफी अमानवीय है। क्या आपको वास्तव में विज़िट किए गए url को LIST के रूप में संग्रहीत करना है? उदाहरण के लिए, यदि आप इसे उरु स्ट्रिंग द्वारा अनुक्रमित, एक तानाशाह के रूप में क्रमबद्ध करते हैं, तो यह एक तरह से क्लीनर होगा:

urls = {'http://www.google.fr/': dict(url='http://www.google.fr/', nbr=1)}

for url in list_of_urls:
    if url in urls:
        urls[url]['nbr'] += 1
    else:
        urls[url] = dict(url=url, nbr=1)

उस दूसरे उदाहरण में ध्यान देने योग्य कुछ बातें:

  • एक एकल के लिए परीक्षण करते समय urlsपूरी urlsसूची से गुजरने की आवश्यकता को हटाने के लिए एक तानाशाह का उपयोग करना देखें url। यह दृष्टिकोण और तेज होगा।
  • dict( )ब्रेसिज़ के बजाय का उपयोग करने से आपका कोड छोटा हो जाता है
  • चर नाम का उपयोग करना list_of_urls, urlsऔर urlपार्स करने के लिए कोड को काफी कठिन बनाते हैं। कुछ स्पष्ट करने के लिए बेहतर है, जैसे कि urls_to_visit, urls_already_visitedऔर current_url। मुझे पता है, यह लंबा है। लेकिन यह स्पष्ट है।

और निश्चित रूप से मैं मान रहा हूं कि dict(url='http://www.google.fr', nbr=1)यह आपके अपने डेटा संरचना का सरलीकरण है, क्योंकि अन्यथा, urlsबस हो सकता है:

urls = {'http://www.google.fr':1}

for url in list_of_urls:
    if url in urls:
        urls[url] += 1
    else:
        urls[url] = 1

जो डिफाल्ट रुख के साथ बहुत सुरुचिपूर्ण हो सकता है :

urls = collections.defaultdict(int)
for url in list_of_urls:
    urls[url] += 1

दूसरा संस्करण अच्छा है क्योंकि मैं बाद में एक सूची के रूप में तानाशाह को बदल सकता हूं।
नटिम

3

पहली बार को छोड़कर, यदि कथन का परीक्षण विफल हो जाता है, तो हर बार किसी शब्द को देखा जाता है। यदि आप बड़ी संख्या में शब्दों की गिनती कर रहे हैं, तो कई संभवतः कई बार होंगे। ऐसी स्थिति में जब किसी मूल्य का आरंभीकरण केवल एक बार होने वाला होता है और उस मूल्य का संवर्द्धन कई बार होता है, जो एक कोशिश बयान का उपयोग करने के लिए सस्ता होता है:

urls_d = {}
for url in list_of_urls:
    try:
        urls_d[url] += 1
    except KeyError:
        urls_d[url] = 1

आप इसके बारे में अधिक पढ़ सकते हैं: https://wiki.python.org/moin/PythonSpeed/PerformureTips

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.