পাইথনে বাছাই করা অ্যারের সূচকগুলি কীভাবে পাবেন


199

আমার একটি সংখ্যাসূচক তালিকা রয়েছে:

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

এখন যদি আমি এই তালিকাটি বাছাই করে নিন [1, 2, 3, 5, 100]। আমি যা চাই তা হল বাছাই করা ক্রমের মূল তালিকা থেকে উপাদানগুলির সূচকগুলি - [0, 1, 2, 4, 3] --- আলা ম্যাটল্যাবের ক্রম ফাংশন যা মান এবং সূচক উভয়ই প্রদান করে।


2
সম্পর্কিত: stackoverflow.com/questions/7851077/...
kevinarpe

@ ইউনতবু এটি কোনও ডুপ (আইএমও) নয়। প্রশ্নটি Numpy.argsort ()
amit

@ অমিত: "বিরোধিতা করে না" বলতে কী বোঝ?
unutbu

@ ইউন্টবু নম্পি.আর্গসোর্ট () এই প্রশ্নের উত্তম উত্তর, এটি যুক্ত থ্রেডের সাথে সংযুক্ত অন্য থ্রেডের (যা আপনিও বন্ধ করেছিলেন এবং আমার পাতলা আপনার হওয়া উচিত নয়) হতে পারে তবে নম্পি হিসাবে আপনি উল্লিখিত প্রশ্নের কাছে নয়। আরগসর্ট () এই দুটির জন্য উত্তম উত্তর, তবে আপনি যেটির কাছে উল্লেখ করেছেন তার পক্ষে নয়।
amit

1
দুর্ভাগ্যক্রমে, এই প্রশ্নের উদাহরণের নির্বাচনের ক্ষেত্রে একটি গুরুতর ত্রুটি রয়েছে কারণ প্রশ্নটি পড়ার দুটি পৃথক পদ্ধতি একই উত্তর দিতে পারে যখন ইনপুটটি সাজানো ক্রমের বাইরে কেবল স্থানান্তর হয়।

উত্তর:


188

আপনি যদি নম্পি ব্যবহার করে থাকেন তবে আপনার কাছে আর্গোর্ট () ফাংশন উপলব্ধ রয়েছে:

>>> 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/...
Bram স্বাগতম Vanroy

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) আপনাকে (সূচক, মান) এর টিপলসযুক্ত একটি তালিকা দেয়:

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

আপনি ধরণের এটি ক্ষণস্থায়ী দ্বারা তালিকা sortedএবং সাজানোর কী (প্রতিটি tuple দ্বিতীয় উপাদান বের করে আনতে একটি ফাংশন উল্লেখ; যে কি lambda। জন্য অবশেষে, প্রতিটি মূল সূচক সাজানো element ব্যবহার আহরণ করা হয় [i[0] for i in ...]তালিকা ধী।


7
আপনি itemgetter(1)ল্যাম্বদা ফাংশনটির পরিবর্তে ব্যবহার করতে পারেন
জন লা রোয়

4
@gnibbler FYI মডিউলে itemgetterফাংশনটি উল্লেখ করছে operator। সুতরাং from operator import itemgetterএটি ব্যবহার করতে।
লরিজ ভি ভি থালো

1
আপনি জিপ ব্যবহার করে বাছাই করা তালিকা এবং সূচকগুলি পেতে পারেন:sorted_items, sorted_inds = zip(*sorted([(i,e) for i,e in enumerate(my_list)], key=itemgetter(1)))
চার্লস এল

@ রোমনবডনারচুক এটি কাজ করে না, x = [3,1,2]; numpy.argsort(x)[1,2,0] ফলন দেয়।
শাহহার_ম


24

সাথে উত্তরগুলি দুর্দান্ত enumerate, তবে আমি ব্যক্তিগতভাবে ল্যাম্বডাকে মান অনুসারে বাছাই করতে পছন্দ করি না। নিম্নলিখিতটি কেবল সূচক এবং মানকে বিপরীত করে এবং এটির আকার দেয়। সুতরাং এটি প্রথমে মান অনুসারে বাছাই করব, তারপরে সূচক অনুসারে।

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

11

সঙ্গে উত্তর Updated enumerateএবং itemgetter:

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

একসাথে তালিকাগুলি জিপ করুন: টুপলে প্রথম উপাদানটি সূচকটি তৈরি করবে, দ্বিতীয়টি মান হবে (তারপরে টিপলের দ্বিতীয় মানটি ব্যবহার করে এটি সাজান, এক্সটি x[1]টিপল)

বা মডিউল itemgetterথেকে ব্যবহার করে operator:

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

1
এই ক্ষেত্রে
জিপের

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)",
)


5

argsortবাহ্যিক লাইব্রেরিগুলি (উদাহরণস্বরূপ NumPy) ব্যবহার করতে চান বা আপনি যদি নির্ভরতা ছাড়াই খাঁটি পাইথন থাকতে চান তবে প্রয়োজনীয়ভাবে আপনাকে একটি করতে হবে , আপনাকে কী বাস্তবায়ন করতে হবে তা নির্ভর করে।

আপনার নিজের জিজ্ঞাসা করা প্রশ্নটি হ'ল: আপনি কি এটি চান want

  • সূচিগুলি যা অ্যারে / তালিকাকে সাজিয়ে রাখবে
  • সূচকগুলি যে উপাদানগুলি সাজানো অ্যারে / তালিকায় থাকবে

দুর্ভাগ্যক্রমে প্রশ্নের উদাহরণটি এটিকে পরিষ্কার করে দেয় না যে পছন্দসই কারণ উভয়ই একই ফলাফল দেবে:

>>> 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 আপনি কেবল ফাংশন 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]), যা ওপি চায় সূচক হিসাবে উপস্থিত হয়।
0 0

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]), যা পুরোপুরি ভাল বলে মনে হচ্ছে, যেহেতু ফলাফলগুলি অ্যারে (ক্রমবর্ধমান) ক্রমে রয়েছে in
0 0

@ 0 0 এর জন্য arr=[1,2,3,100, 5, 9], আমি আউটপুটটি প্রত্যাশা করব inds=[0,1,2,5,3,4], কারণ এটি সেই ক্রম যা আপনি উপাদানগুলি ক্রমবর্ধমান (ক্রমবর্ধমান) অর্ডার করবেন - 1 0 এর স্থানে, 1 ম স্থানে 2, ...., 5 তৃতীয় স্থান এবং 9 র্থ স্থানে 9। এই আউটপুটটি পেতে ( inds) আমার argsortদু'বার চালানো দরকার , যেমনটি আমি উল্লেখ করেছি।
শাহহার_ম

সুতরাং সেই সূচকগুলি অ্যারের উপাদানগুলির এক ধরণের র‌্যাঙ্কিং (0 তম স্থান, 1 ম স্থান, ইত্যাদি)। ম্যাটল্যাব-এর ওপিরsort উল্লেখটি বিবেচনা করে , আমি গণ্য করি যে ওপি অন্যান্য কার্যকারিতা চায়, অনেকটা np.argsortসাধারণত ব্যবহৃত হয় (যেখানে arr[np.argsort[arr]]শেষ স্যাটেলাইটের উদাহরণ হিসাবে যেমন বাছাই করা অ্যারেটি ব্যবহার করতে পারেন )। আপনার উত্তর পরিবর্তে এই ক্ষেত্রে / প্রশ্নের ক্ষেত্রে প্রযোজ্য ।
0 0

0

এনপি হিসাবে নাম্বার আমদানি করুন

সূচকের জন্য

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])

আরগসর্ট 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()

`

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.