पायथन में क्रमबद्ध सरणी के सूचकांक कैसे प्राप्त करें


199

मेरे पास एक संख्यात्मक सूची है:

myList = [1, 2, 3, 100, 5]

अब अगर मैं इस सूची को प्राप्त करने के लिए छाँटूँ [1, 2, 3, 5, 100]। मैं जो चाहता हूं वह छांटे गए क्रम में मूल सूची से तत्वों [0, 1, 2, 4, 3] का सूचकांक है।



@unutbu यह एक डुओ (IMO) नहीं है। सवाल खंडन Numpy.argsort () का उपयोग नहीं करता है
अमित

@amit: "विरोध नहीं करता है" से आपका क्या तात्पर्य है?
अनुतु ०

@unutbu Numpy.argsort () इस सवाल का एक अच्छा जवाब है, यह दूसरे धागे से जुड़ा हुआ एक दुपट्टा हो सकता है (जो आपने भी बंद कर दिया है और मैं आपके पास पतला होना चाहिए) लेकिन आपके द्वारा उल्लेखित नहीं के रूप में नम्पी। argsort () इन दोनों के लिए ठीक उत्तर है, लेकिन आपके द्वारा संदर्भित के लिए नहीं।
अमित

1
दुर्भाग्य से, इस सवाल के उदाहरण के चुनाव में एक गंभीर दोष है, क्योंकि प्रश्न को पढ़ने के दो अलग-अलग तरीकों से एक ही जवाब मिलेगा जब इनपुट केवल क्रमबद्ध क्रम से बाहर एक ट्रांसपोज़िशन है।

जवाबों:


188

यदि आप numpy का उपयोग कर रहे हैं, तो आपके पास argsort () फ़ंक्शन उपलब्ध है:

>>> import numpy
>>> numpy.argsort(myList)
array([0, 1, 2, 4, 3])

http://docs.scipy.org/doc/numpy/reference/generated/numpy.argsort.html

यह उन तर्कों को लौटाता है जो सरणी या सूची को क्रमबद्ध करेंगे।


ध्यान दें कि यह वह नहीं हो सकता जो आप चाहते हैं! इस प्रश्न को देखें: stackoverflow.com/questions/54388972/…
ब्रैम वनरॉय

147

आगे कुछ इस तरह:

>>> myList = [1, 2, 3, 100, 5]
>>> [i[0] for i in sorted(enumerate(myList), key=lambda x:x[1])]
[0, 1, 2, 4, 3]

enumerate(myList) आपको एक सूची देता है जिसमें (इंडेक्स, वैल्यू) के tuples होते हैं:

[(0, 1), (1, 2), (2, 3), (3, 100), (4, 5)]

आप सूची को पास sortedकरके सॉर्ट कुंजी को निकालने के लिए किसी फ़ंक्शन को निर्दिष्ट करते हैं (प्रत्येक ट्यूपर का दूसरा तत्व)। यह है कि इसके lambdaलिए क्या है। अंत में, सूची क्रम का उपयोग करके प्रत्येक सॉर्ट किए गए तत्व का मूल सूचकांक निकाला जाता है [i[0] for i in ...]


7
आप itemgetter(1)लैम्बडा फंक्शन के बजाय उपयोग कर सकते हैं
जॉन ला रूय

4
@gnibbler मॉड्यूल itemgetterमें फ़ंक्शन का उल्लेख कर रहा है operator, FYI करें। इसलिए from operator import itemgetterइसका इस्तेमाल जरूर करें।
लॉरिट्ज वी। थुलोव

1
आप क्रमबद्ध सूची प्राप्त कर सकते हैं और ज़िप का उपयोग करके संकेत कर सकते हैं:sorted_items, sorted_inds = zip(*sorted([(i,e) for i,e in enumerate(my_list)], key=itemgetter(1)))
चार्ल्स एल।

@RomanBodnarchuk इस काम नहीं करता है, x = [3,1,2]; numpy.argsort(x)पैदावार [1,2,0]।
shahar_m


24

के साथ उत्तर enumerateअच्छे हैं, लेकिन मुझे व्यक्तिगत रूप से पसंद नहीं है कि लैम्बडा का उपयोग मूल्य के आधार पर किया जाता है। निम्नलिखित सिर्फ सूचकांक और मूल्य को उलट देता है, और उस तरह से। तो यह पहले मूल्य के आधार पर क्रमबद्ध करेगा, फिर सूचकांक द्वारा।

sorted((e,i) for i,e in enumerate(myList))

11

के साथ अपडेट किया गया उत्तर enumerateऔर itemgetter:

sorted(enumerate(a), key=lambda x: x[1])
# [(0, 1), (1, 2), (2, 3), (4, 5), (3, 100)]

सूचियों को एक साथ जिप करें: टपल में पहला तत्व इंडेक्स होगा, दूसरा वैल्यू है (फिर इसे टुपल के दूसरे मान का उपयोग करके सॉर्ट करें x[1], x टपल है)

या मॉड्यूल itemgetterसे उपयोग कर operatorरहे हैं:

from operator import itemgetter
sorted(enumerate(a), key=itemgetter(1))

1
enumerate इस मामले में ज़िप से अधिक उपयुक्त लगता है
njzk2

10

मैंने परफ्लोट (मेरा एक प्रोजेक्ट) के साथ इन पर एक त्वरित प्रदर्शन जांच की और पाया कि इसके अलावा और कुछ भी सिफारिश करना कठिन है लेकिन सुन्न (लॉग स्केल पर ध्यान दें):

यहां छवि विवरण दर्ज करें


प्लॉट को फिर से तैयार करने के लिए कोड:

import perfplot
import numpy


def sorted_enumerate(seq):
    return [i for (v, i) in sorted((v, i) for (i, v) in enumerate(seq))]


def sorted_enumerate_key(seq):
    return [x for x, y in sorted(enumerate(seq), key=lambda x: x[1])]


def sorted_range(seq):
    return sorted(range(len(seq)), key=seq.__getitem__)


def numpy_argsort(x):
    return numpy.argsort(x)


perfplot.save(
    "argsort.png",
    setup=lambda n: numpy.random.rand(n),
    kernels=[sorted_enumerate, sorted_enumerate_key, sorted_range, numpy_argsort],
    n_range=[2 ** k for k in range(15)],
    xlabel="len(x)",
)

6

यदि आप खसखस ​​का उपयोग नहीं करना चाहते हैं,

sorted(range(len(seq)), key=seq.__getitem__)

सबसे तेज़ है, जैसा यहाँ दिखाया गया है


5

अनिवार्य रूप से आपको एक करने की आवश्यकता है argsort, आपको जो कार्यान्वयन की आवश्यकता है वह निर्भर करता है यदि आप बाहरी पुस्तकालयों (जैसे कि न्यूमपी) का उपयोग करना चाहते हैं या यदि आप निर्भरता के बिना शुद्ध-पायथन रहना चाहते हैं।

सवाल जो आपको खुद से पूछने की जरूरत है: क्या आप चाहते हैं

  • सूचक जो सरणी / सूची को क्रमबद्ध करेंगे
  • यह संकेत मिलता है कि तत्व क्रमबद्ध सरणी / सूची में होंगे

दुर्भाग्य से प्रश्न में उदाहरण यह स्पष्ट नहीं करता है कि वांछित क्या है क्योंकि दोनों एक ही परिणाम देंगे:

>>> arr = np.array([1, 2, 3, 100, 5])

>>> np.argsort(np.argsort(arr))
array([0, 1, 2, 4, 3], dtype=int64)

>>> np.argsort(arr)
array([0, 1, 2, 4, 3], dtype=int64)

argsortकार्यान्वयन चुनना

यदि आपके पास अपने निपटान में नुम्पी है तो आप बस फ़ंक्शन numpy.argsortया विधि का उपयोग कर सकते हैं numpy.ndarray.argsort

NumPy के बिना एक कार्यान्वयन का उल्लेख पहले से ही कुछ अन्य उत्तरों में किया गया था, इसलिए मैं यहाँ बेंचमार्क उत्तर के अनुसार सबसे तेज़ समाधान को फिर से लाऊँगा

def argsort(l):
    return sorted(range(len(l)), key=l.__getitem__)

सरणी / सूची को सॉर्ट करने वाले सूचकांकों को प्राप्त करना

सरणी / सूची को सॉर्ट करने वाले सूचकांकों को प्राप्त करने के लिए आप बस argsortसरणी या सूची पर कॉल कर सकते हैं । मैं यहाँ NumPy संस्करणों का उपयोग कर रहा हूँ, लेकिन पायथन कार्यान्वयन को समान परिणाम देना चाहिए

>>> arr = np.array([3, 1, 2, 4])
>>> np.argsort(arr)
array([1, 2, 0, 3], dtype=int64)

परिणाम में सूचक होते हैं जो क्रमबद्ध सरणी प्राप्त करने के लिए आवश्यक होते हैं।

चूँकि सॉर्ट किया गया एरे होगा [1, 2, 3, 4], एर्गोस्र्ड ऐरे में मूल में इन तत्वों के सूचक होते हैं।

  • सबसे छोटा मान है 1और यह 1मूल में सूचकांक पर है इसलिए परिणाम का पहला तत्व है 1
  • 2सूचकांक पर है 2मूल में तो परिणाम का दूसरा तत्व है 2
  • 3सूचकांक पर है 0मूल में तो परिणाम के तीसरे तत्व है 0
  • सबसे बड़ा मूल्य 4और यह 3मूल में सूचकांक पर है इसलिए परिणाम का अंतिम तत्व है 3

तत्वों को छांटे गए सरणी / सूची में होता है

इस मामले में आपको argsort दो बार आवेदन करना होगा :

>>> arr = np.array([3, 1, 2, 4])
>>> np.argsort(np.argsort(arr))
array([2, 0, 1, 3], dtype=int64)

इस मामले में :

  • मूल का पहला तत्व है 3, जो तीसरा सबसे बड़ा मूल्य है, इसलिए यह 2क्रमबद्ध सरणी / सूची में सूचकांक होगा इसलिए पहला तत्व है 2
  • मूल का दूसरा तत्व है 1, जो सबसे छोटा मान है, इसलिए यह 0क्रमबद्ध सरणी / सूची में सूचकांक होगा इसलिए दूसरा तत्व है 0
  • मूल का तीसरा तत्व है 2, जो दूसरा सबसे छोटा मूल्य है, इसलिए यह 1क्रमबद्ध सरणी / सूची में सूचकांक होगा ताकि तीसरा भाग है 1
  • मूल का चौथा तत्व है, 4जो सबसे बड़ा मूल्य है, इसलिए यह 3क्रमबद्ध सरणी / सूची में सूचकांक होगा इसलिए अंतिम तत्व है 3

4

अन्य जवाब गलत हैं।

argsortएक बार चलाने का उपाय नहीं है। उदाहरण के लिए, निम्न कोड:

import numpy as np
x = [3,1,2]
np.argsort(x)

पैदावार array([1, 2, 0], dtype=int64)जो हम नहीं चाहते हैं।

उत्तर argsortदो बार चलाने के लिए होना चाहिए :

import numpy as np
x = [3,1,2]
np.argsort(np.argsort(x))

देता है array([2, 0, 1], dtype=int64)के रूप में उम्मीद।


आपका दावा x[2](3) सबसे छोटा तत्व बनाता है , और x[1](1) सबसे बड़ा तत्व (क्योंकि पूर्णांकों को क्रमबद्ध करने से उन्हें सबसे छोटे मूल्य से लेकर सबसे बड़े मूल्य तक का ऑर्डर देता है)। इसके अलावा, ओपी उदाहरण के साथ, एक एकल np.argsort([1, 2, 3, 100, 5])पैदावार array([0, 1, 2, 4, 3]), जो ओपी चाहता है सूचकांकों के लिए प्रतीत होता है।
१ ०

1
@ 0 0 आपका उदाहरण एक विशिष्ट मामला है। अगर हम दौड़ते हैं arr = [1,2,3,100, 5, 9] res = np.argsort(arr) print(res)तो हम [0 1 2 4 5 3]गलत हैं।
शहर_म

मैं स्पष्ट नहीं हूं कि क्या गलत है: arr[res]पैदावार array([ 1, 2, 3, 5, 9, 100]), जो पूरी तरह से ठीक लगती है, क्योंकि परिणामस्वरूप सरणी (बढ़ती) क्रम में है।
0 0

@ 0 0 के लिए arr=[1,2,3,100, 5, 9], मैं आउटपुट के होने की उम्मीद करता हूं inds=[0,1,2,5,3,4], क्योंकि यह वह क्रम है जिसमें आप तत्वों को बढ़ाएंगे (तेजी से) - 1 0 स्थान पर है, 2 1 स्थान पर है, ...., 5 ऑन 1 4 वें स्थान पर 3 और 9 वें स्थान पर है। उस आउटपुट को प्राप्त करने के लिए ( inds) मुझे argsortदो बार चलाने की आवश्यकता है , जैसे मैंने उल्लेख किया है।
shahar_m

तो उन सूचक सरणी तत्वों (0 स्थान, 1 स्थान, आदि) की रैंकिंग का एक प्रकार है। MATLAB केsort लिए ओपी के उल्लेख को देखते हुए , मुझे लगता है कि ओपी अन्य कार्यक्षमता चाहता है, बहुत np.argsortकुछ सामान्य रूप से उपयोग किया जाता है (जहां व्यक्ति arr[np.argsort[arr]]अंतिम MATLAB उदाहरण में, सॉर्ट किए गए सरणी को प्राप्त करने के लिए उपयोग कर सकता है )। आपका उत्तर इस मामले / प्रश्न पर लागू होता है ।
0 0

0

सुन्न को एनपी के रूप में आयात करें

INDEX के लिए

S=[11,2,44,55,66,0,10,3,33]

r=np.argsort(S)

[output]=array([5, 1, 7, 6, 0, 8, 2, 3, 4])

argsort सॉर्ट किए गए क्रम में S के सूचकांकों को लौटाता है

मूल्य के लिए

np.sort(S)

[output]=array([ 0,  2,  3, 10, 11, 33, 44, 55, 66])

0

हम 0 से n-1 तक अनुक्रमणिकाओं का एक और सरणी बनाएंगे और फिर इसे मूल सरणी पर पिन करें और फिर मूल मानों के आधार पर इसे सॉर्ट करें

ar = [1,2,3,4,5]
new_ar = list(zip(ar,[i for i in range(len(ar))]))
new_ar.sort()

`

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