इतने सारे समाधानों के प्रस्ताव के साथ, मैं किसी को भी आश्चर्यचकित नहीं कर रहा हूं कि मैं एक स्पष्ट (गैर-योग्य, लेकिन तुलनीय तत्वों के लिए) क्या विचार करूंगा - [ itertools.groupby
] [१]। itertools
तेज, पुन: प्रयोज्य कार्यक्षमता प्रदान करता है, और आपको कुछ पेचीदा तर्क को अच्छी तरह से परीक्षण किए गए मानक पुस्तकालय घटकों को सौंपने देता है। उदाहरण के लिए विचार करें:
import itertools
import operator
def most_common(L):
# get an iterable of (item, iterable) pairs
SL = sorted((x, i) for i, x in enumerate(L))
# print 'SL:', SL
groups = itertools.groupby(SL, key=operator.itemgetter(0))
# auxiliary function to get "quality" for an item
def _auxfun(g):
item, iterable = g
count = 0
min_index = len(L)
for _, where in iterable:
count += 1
min_index = min(min_index, where)
# print 'item %r, count %r, minind %r' % (item, count, min_index)
return count, -min_index
# pick the highest-count/earliest item
return max(groups, key=_auxfun)[0]
यह अधिक स्पष्ट रूप से लिखा जा सकता है, निश्चित रूप से, लेकिन मैं अधिकतम स्पष्टता के लिए लक्ष्य बना रहा हूं। print
कार्रवाई में मशीनरी को बेहतर ढंग से देखने के लिए दो बयानों को अनियोजित किया जा सकता है; उदाहरण के लिए, प्रिंट के साथ अपूर्ण:
print most_common(['goose', 'duck', 'duck', 'goose'])
का उत्सर्जन करता है:
SL: [('duck', 1), ('duck', 2), ('goose', 0), ('goose', 3)]
item 'duck', count 2, minind 1
item 'goose', count 2, minind 0
goose
जैसा कि आप देखते हैं, SL
जोड़ों की एक सूची है, प्रत्येक जोड़ी एक आइटम है जो मूल सूची में आइटम के सूचकांक के बाद है (महत्वपूर्ण स्थिति को लागू करने के लिए, यदि "सबसे आम" समान उच्चतम गिनती वाले आइटम> 1 हैं, तो परिणाम अवश्य होगा जल्द से जल्द होने वाली)।
groupby
केवल आइटम के माध्यम से समूह (के माध्यम से operator.itemgetter
)। max
अभिकलन के दौरान समूहन के अनुसार एक बार कहा जाने वाला सहायक कार्य, एक समूह को प्राप्त करता है और आंतरिक रूप से अनपैक करता है - दो वस्तुओं के साथ एक ट्यूपल (item, iterable)
जहां चलने योग्य आइटम भी दो-आइटम ट्यूपल हैं, (item, original index)
[[आइटम SL
]]।
फिर सहायक फ़ंक्शन समूह के पुनरावृत्ति में प्रविष्टियों की गणना और न्यूनतम मूल सूचकांक दोनों को निर्धारित करने के लिए एक लूप का उपयोग करता है ; यह उन सभी को "गुणवत्ता कुंजी" के रूप में देता है, जो मिनिमम इंडेक्स साइन-बदल गए हैं इसलिए max
ऑपरेशन उन वस्तुओं पर "बेहतर" विचार करेगा जो मूल सूची में पहले हुए थे।
यह कोड बहुत आसान हो सकता है अगर यह समय और स्थान में बड़े-ओ मुद्दों के बारे में थोड़ा कम चिंतित हो , जैसे ...:
def most_common(L):
groups = itertools.groupby(sorted(L))
def _auxfun((item, iterable)):
return len(list(iterable)), -L.index(item)
return max(groups, key=_auxfun)[0]
एक ही मूल विचार, बस और अधिक सरल रूप से व्यक्त ... लेकिन, अफसोस, एक अतिरिक्त O (N) सहायक स्थान (सूचियों के समूहों के पुनरावृत्तियों को मूर्त रूप देने के लिए) और O (N वर्ग) समय ( L.index
प्रत्येक आइटम की अधिकता पाने के लिए ) । जबकि समयपूर्व अनुकूलन प्रोग्रामिंग में सभी बुराई की जड़ है, जब ओ (एन लॉग एन) एक उपलब्ध होने पर जानबूझकर ओ (एन स्क्वार्ड) दृष्टिकोण उठाता है, स्केलेबिलिटी के दाने के मुकाबले बहुत अधिक हो जाता है! -
अंत में, स्पष्टता और प्रदर्शन के लिए "ओनलीनेर्स" पसंद करने वालों के लिए, एक बोनस 1-लाइनर संस्करण जो उपयुक्त रूप से आम के नाम :-) है।
from itertools import groupby as g
def most_common_oneliner(L):
return max(g(sorted(L)), key=lambda(x, v):(len(list(v)),-L.index(x)))[0]