অন্য তালিকা থেকে মানের উপর ভিত্তি করে তালিকাটি বাছাই করছেন?


368

আমার কাছে স্ট্রিংগুলির একটি তালিকা রয়েছে:

X = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
Y = [ 0,   1,   1,   0,   1,   2,   2,   0,   1 ]

নিম্নলিখিত আউটপুটটি পেতে Y এর মান ব্যবহার করে এক্সকে বাছাই করার সবচেয়ে সংক্ষিপ্ততম উপায় কী?

["a", "d", "h", "b", "c", "e", "i", "f", "g"]

একই "কী" থাকা উপাদানগুলির ক্রম কোনও ব্যাপার নয়। আমি forকনস্ট্রাক্টসের ব্যবহার অবলম্বন করতে পারি তবে যদি আরও ছোট উপায় হয় তবে আমি আগ্রহী। কোন পরামর্শ?


ডেটা ষড়যন্ত্র riza উত্তর সহায়ক হতে পারে, যেহেতু জিপ (* সাজানো (জিপ (x, y), কী = ল্যামডা যুগল: যুগল [0])) আয় উভয় সাজানো X এবং Y এক্স এর মান সাজানো
Jojo

উত্তর:


478

সংক্ষিপ্ততম কোড

[x for _,x in sorted(zip(Y,X))]

উদাহরণ:

X = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
Y = [ 0,   1,   1,    0,   1,   2,   2,   0,   1]

Z = [x for _,x in sorted(zip(Y,X))]
print(Z)  # ["a", "d", "h", "b", "c", "e", "i", "f", "g"]

সাধারণভাবে বলতে

[x for _, x in sorted(zip(Y,X), key=lambda pair: pair[0])]

ব্যাখ্যা:

  1. zipদুটি listএস।
  2. একটি নতুন তৈরি, ব্যবহারের listউপর ভিত্তি করে সাজানো ।zipsorted()
  3. একটি তালিকা ধী ব্যবহার নির্যাস সাজানো, জিপ করা থেকে প্রতিটি জোড়া প্রথম উপাদান list

কিভাবে সেটে \ ব্যবহার সম্পর্কে আরও তথ্যের জন্য keyপাশাপাশি প্যারামিটার হিসাবে sortedসাধারণভাবে ফাংশন, কটাক্ষপাত করা এই



117
এটি সঠিক, তবে আমি এই নোটটি যুক্ত করব যে আপনি যদি একই অ্যারে দ্বারা একাধিক অ্যারে বাছাই করার চেষ্টা করছেন তবে এটি আশানুরূপভাবে কাজ করবে না, যেহেতু বাছাইয়ের জন্য ব্যবহৃত চাবিটি হ'ল (y, x) , শুধু y নয় আপনার পরিবর্তে [x এর জন্য (y, x) সাজানো (জিপ (ওয়াই, এক্স), কী =
ল্যাম্বদা

1
ভাল সমাধান! তবে এটি হওয়া উচিত: তালিকাটি জোড়াগুলির প্রথম উপাদান সম্পর্কিত অর্ডার করা হয়, এবং বোধগম্যতা জোড়গুলির 'দ্বিতীয়' উপাদানটি বের করে।
মাস্টারকন্ট্রোল প্রোগ্রাম

স্টোরেজ করার সময় এই সমাধানটি দুর্বল। যখনই সম্ভব স্থানের মধ্যে বাছাই করা পছন্দ করা হয়।
হেটফিন্ড

107

দুটি তালিকা একসাথে জিপ করুন, এটি বাছাই করুন, তারপরে আপনি যে অংশগুলি চান তা নিন:

>>> yx = zip(Y, X)
>>> yx
[(0, 'a'), (1, 'b'), (1, 'c'), (0, 'd'), (1, 'e'), (2, 'f'), (2, 'g'), (0, 'h'), (1, 'i')]
>>> yx.sort()
>>> yx
[(0, 'a'), (0, 'd'), (0, 'h'), (1, 'b'), (1, 'c'), (1, 'e'), (1, 'i'), (2, 'f'), (2, 'g')]
>>> x_sorted = [x for y, x in yx]
>>> x_sorted
['a', 'd', 'h', 'b', 'c', 'e', 'i', 'f', 'g']

এগুলি একত্রিত করার জন্য:

[x for y, x in sorted(zip(Y, X))]

1
যদি এটির Xতালিকা strথাকে তবে এটি ঠিক আছে, তবে <কিছু সংখ্যক আইটেমের জন্য সংজ্ঞায়িত না হওয়ার কোনও সম্ভাবনা থাকলে সতর্ক থাকুন X- উদাহরণস্বরূপ - সেগুলির মধ্যে কিছু যদি হয়None
জন লা রুই

1
আমরা যখন কোনও জিপ অবজেক্টের উপর বাছাই করার চেষ্টা করি তখন AttributeError: 'zip' object has no attribute 'sort'আমি এখন যা পাচ্ছি।
আশ উপাধ্যায়

2
আপনি পাইথন ৩ ব্যবহার করছেন Py পাইথন ২ এ জিপ একটি তালিকা তৈরি করেছে। এখন এটি একটি পুনরাবৃত্তিযোগ্য বস্তু উত্পাদন করে। sorted(zip(...))এখনও কাজ করা উচিত, বা: them = list(zip(...)); them.sort()
নেড ব্যাচেল্ডার

77

এছাড়াও, যদি আপনি ন্যাপি অ্যারেগুলি ব্যবহার করতে আপত্তি করেন না (বা বাস্তবে ইতিমধ্যে নপি অ্যারেগুলি ব্যবহার করছেন ...), তবে এখানে আরও একটি দুর্দান্ত সমাধান রয়েছে:

people = ['Jim', 'Pam', 'Micheal', 'Dwight']
ages = [27, 25, 4, 9]

import numpy
people = numpy.array(people)
ages = numpy.array(ages)
inds = ages.argsort()
sortedPeople = people[inds]

আমি এটি এখানে পেয়েছি: http://scienceoss.com/sort-one-list-by-another-list/


1
বড় অ্যারে / ভেক্টরগুলির জন্য, নম্পির সাথে এই দ্রবণটি উপকারী!
মাস্টারকন্ট্রোল প্রোগ্রাম

1
তারা ইতিমধ্যেই numpy অ্যারে হয় তাহলে, এটি কেবল এর sortedArray1= array1[array2.argsort()]। এবং এটি 2D অ্যারের নির্দিষ্ট কলাম দ্বারা একাধিক তালিকাগুলি বাছাই করা সহজ করে তোলে: যেমন অ্যারে 2 sortedArray1= array1[array2[:,2].argsort()]এর তৃতীয় কলামের মান অনুসারে অ্যারে 1 (যা একাধিক কলাম থাকতে পারে) বাছাই করে।
অ্যারন ব্রামসন

40

আমার কাছে সবচেয়ে সুস্পষ্ট সমাধান হ'ল keyকীওয়ার্ড আরগটি ব্যবহার করা ।

>>> X = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
>>> Y = [ 0,   1,   1,    0,   1,   2,   2,   0,   1]
>>> keydict = dict(zip(X, Y))
>>> X.sort(key=keydict.get)
>>> X
['a', 'd', 'h', 'b', 'c', 'e', 'i', 'f', 'g']

মনে রাখবেন যে আপনি যদি যত্নশীল হন তবে আপনি এটি ওয়ান-লাইনারে সংক্ষিপ্ত করতে পারেন:

>>> X.sort(key=dict(zip(X, Y)).get)

2
এটির কি দরকার যে এক্স এর মানগুলি অপ্রয়োজনীয়?
জ্যাক পেঙ্গ

15

আমি এখানে একটি তালিকা অনুসারে একটি তালিকা বাছাই করতে এখানে এসেছি যেখানে মানগুলি মেলে।

list_a = ['foo', 'bar', 'baz']
list_b = ['baz', 'bar', 'foo']
sorted(list_b, key=lambda x: list_a.index(x))
# ['foo', 'bar', 'baz']

1
এটা কি পারফর্মেন্ট?
এএফপি_ 555

কোন সুত্র নেই. আপনি যা খুশি তা ফিরিয়ে দিন।
ন্যাকজিচলসন

1
এটি একটি খারাপ ধারণা। বাছাইয়ের ফলে ও (এন) অনুসন্ধান indexকরবে perform list_aO(N² log N)
রিচার্ড

ধন্যবাদ, পারফরম্যান্সের বিষয়টি গুরুত্বপূর্ণ হলে এটি করবেন না!
ন্যাকজিচলসন

15

more_itertools সমান্তরালে পুনরাবৃত্তিগুলি বাছাই করার জন্য একটি সরঞ্জাম রয়েছে:

প্রদত্ত

from more_itertools import sort_together


X = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
Y = [ 0,   1,   1,    0,   1,   2,   2,   0,   1]

ডেমো

sort_together([Y, X])[1]
# ('a', 'd', 'h', 'b', 'c', 'e', 'i', 'f', 'g')

13

আমি বাছাই করা সূচকগুলির একটি তালিকা রাখতে চাই। এইভাবে, আমি উত্স তালিকার মতো একই তালিকায় যে কোনও তালিকা সাজিয়ে রাখতে পারি। একবার আপনার বাছাই করা সূচকগুলির একটি তালিকা হয়ে গেলে, একটি সাধারণ তালিকা অনুধাবন কৌশলটি করবে:

X = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
Y = [ 0,   1,   1,    0,   1,   2,   2,   0,   1]

sorted_y_idx_list = sorted(range(len(Y)),key=lambda x:Y[x])
Xs = [X[i] for i in sorted_y_idx_list ]

print( "Xs:", Xs )
# prints: Xs: ["a", "d", "h", "b", "c", "e", "i", "f", "g"]

নোট করুন যে বাছাই করা সূচক তালিকাটি ব্যবহার করেও অর্জন করা যেতে পারে numpy.argsort()


12

বেশ কয়েকটি উত্তর মিলিয়ে অন্য একটি বিকল্প।

zip(*sorted(zip(Y,X)))[1]

পাইথন 3 এর জন্য কাজ করার জন্য:

list(zip(*sorted(zip(B,A))))[1]

7

জিপ, দ্বিতীয় কলাম অনুসারে বাছাই করুন, প্রথম কলামটি ফিরুন।

zip(*sorted(zip(X,Y), key=operator.itemgetter(1)))[0]

দ্রষ্টব্য: কী = অপারেটর.মিটমিটার (1) সদৃশ সমস্যার সমাধান করে
কিথ

জিপ সাবস্ক্রিপ্টযোগ্য নয় ... আপনার অবশ্যই ব্যবহার করতে হবেlist(zip(*sorted(zip(X,Y), key=operator.itemgetter(1))))[0]
র‌্যাফেল

@ কিথ নকল ইস্যু?
জোশ

যদি একের বেশি সংখ্যক মিল থাকে তবে তা প্রথমটি পায়
কিথ

3

দ্রুত ওয়ান-লাইনার

list_a = [5,4,3,2,1]
list_b = [1,1.5,1.75,2,3,3.5,3.75,4,5]

বলুন আপনি তালিকার সাথে তালিকার সাথে তালিকার তালিকা চান খ।

orderedList =  sorted(list_a, key=lambda x: list_b.index(x))

বৃহত্তর মানগুলিতে একটি ছোট তালিকা অর্ডার করার প্রয়োজনে এটি সহায়ক। ধরে নিচ্ছি যে বৃহত্তর তালিকায় ছোট তালিকাতে সমস্ত মান রয়েছে, এটি করা যায়।


এটি ওপির প্রশ্নের সমাধান করে না। আপনি কি নমুনা তালিকা Xএবং এটি ব্যবহার করে দেখেছেন Y?
আরেহ লাইব বৃষ

এটি একটি খারাপ ধারণা। বাছাইয়ের ফলে ও (এন) অনুসন্ধান indexকরবে perform list_bO(N² log N)
রিচার্ড

1

আপনি pandas Seriesপ্রাথমিক তালিকা হিসাবে dataএবং অন্যান্য তালিকাটি ব্যবহার করে একটি তৈরি করতে পারেন indexএবং তারপরে কেবল সূচক অনুসারে বাছাই করুন:

import pandas as pd
pd.Series(data=X,index=Y).sort_index().tolist()

আউটপুট:

['a', 'd', 'h', 'b', 'c', 'e', 'i', 'f', 'g']

1

যদি আপনি উভয় সাজানো তালিকা (পাইথন 3) পেতে চান তবে হোয়াট্যাংসের উত্তর এখানে answer

X = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
Y = [ 0,   1,   1,    0,   1,   2,   2,   0,   1]

Zx, Zy = zip(*[(x, y) for x, y in sorted(zip(Y, X))])

print(list(Zx))  # [0, 0, 0, 1, 1, 1, 1, 2, 2]
print(list(Zy))  # ['a', 'd', 'h', 'b', 'c', 'e', 'i', 'f', 'g']

শুধু মনে রাখবেন জেডএক্স এবং জাই টিপলস। এটি করার আরও ভাল উপায় থাকলে আমিও ঘুরছি।

সতর্কতা: আপনি খালি তালিকাগুলি দিয়ে চালালে এটি ক্র্যাশ হয়ে যায়।


1

আমি একটি আরও সাধারণ ক্রিয়াকলাপ তৈরি করেছি, যা @ হোয়াটংয়ের উত্তর দ্বারা অনুপ্রাণিত হয়ে অন্য একটির উপর ভিত্তি করে দুটিরও বেশি তালিকাগুলি সাজায়।

def parallel_sort(*lists):
    """
    Sorts the given lists, based on the first one.
    :param lists: lists to be sorted

    :return: a tuple containing the sorted lists
    """

    # Create the initially empty lists to later store the sorted items
    sorted_lists = tuple([] for _ in range(len(lists)))

    # Unpack the lists, sort them, zip them and iterate over them
    for t in sorted(zip(*lists)):
        # list items are now sorted based on the first list
        for i, item in enumerate(t):    # for each item...
            sorted_lists[i].append(item)  # ...store it in the appropriate list

    return sorted_lists

0
list1 = ['a','b','c','d','e','f','g','h','i']
list2 = [0,1,1,0,1,2,2,0,1]

output=[]
cur_loclist = []

উপস্থিত অনন্য মান পেতে list2

list_set = set(list2)

ইনডেক্সের লোকেশনটি সন্ধান করতে list2

list_str = ''.join(str(s) for s in list2)

ইনডেক্সের অবস্থান list2ব্যবহার করে ট্র্যাক করা হয়েছেcur_loclist

[0, 3, 7, 1, 2, 4, 8, 5, 6]

for i in list_set:
cur_loc = list_str.find(str(i))

while cur_loc >= 0:
    cur_loclist.append(cur_loc)
    cur_loc = list_str.find(str(i),cur_loc+1)

print(cur_loclist)

for i in range(0,len(cur_loclist)):
output.append(list1[cur_loclist[i]])
print(output)

0

এটি একটি পুরানো প্রশ্ন তবে আমার পোস্ট করা উত্তরগুলি দেখে কিছু উত্তর আসলে zipস্ক্রিপ্টযোগ্য নয় বলে কাজ করে না। অন্যান্য উত্তরগুলি বিরক্ত করে নাimport operator এবং এখানে এই মডিউল এবং এর সুবিধা সম্পর্কে আরও তথ্য সরবরাহ করে না।

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

X = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
Y = [ 0,   1,   1,   0,   1,   2,   2,   0,   1 ]

" সাজসজ্জা-বাছাই-আন্ডারকোর্ট " আইডিয়াম ব্যবহার করে

90 এর দশকে পার্লে এই প্যাটার্নটি জনপ্রিয় করে তোলেন আর। শোয়ার্জ-এর পরে এটি শোয়ার্জিয়ান_ট্রান্সফর্ম হিসাবেও পরিচিত :

# Zip (decorate), sort and unzip (undecorate).
# Converting to list to script the output and extract X
list(zip(*(sorted(zip(Y,X)))))[1]                                                                                                                       
# Results in: ('a', 'd', 'h', 'b', 'c', 'e', 'i', 'f', 'g')

নোট করুন যে এই ক্ষেত্রে Yএবং Xসাজানো এবং ডিকোসোগ্রাফিকভাবে তুলনা করা হয়। যে, প্রথম আইটেম (থেকে Y) তুলনা করা হয়; এবং যদি সেগুলি একই হয় তবে দ্বিতীয় আইটেমগুলি (থেকে X) তুলনা করা হবে ইত্যাদি। এটি অস্থির তৈরি করতে পারেডিক্সেলিকেটগুলি তাদের মূল ক্রমে রাখার জন্য যদি আপনি অভিধান সংক্রান্ত অর্ডারের জন্য মূল তালিকা সূচকগুলি অন্তর্ভুক্ত না করেন তবে আউটপুট ।

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

এটি আপনাকে কীভাবে ইনপুটটি বাছাই করতে দেয় তার উপর আরও সরাসরি নিয়ন্ত্রণ দেয়, যাতে আপনি নির্দিষ্ট কীটি বাছাই করে কেবল স্থিতিশীলতা বাছাই করতে পারেন। আরও উদাহরণ দেখুন এখানে

import operator    

# Sort by Y (1) and extract X [0]
list(zip(*sorted(zip(X,Y), key=operator.itemgetter(1))))[0]                                                                                                 
# Results in: ('a', 'd', 'h', 'b', 'c', 'e', 'i', 'f', 'g')
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.