সঠিকভাবে কীভাবে দুটি তালিকা (একে অপরের রেফারেন্স) বাছাই করতে হবে


139

বলুন আমার দুটি তালিকা রয়েছে:

list1 = [3, 2, 4, 1, 1]
list2 = ['three', 'two', 'four', 'one', 'one2']

আমি যদি দৌড়ে যাই তবে list1.sort()এটি এটি সাজিয়ে ফেলবে তবে পাওয়ার [1,1,2,3,4]উপায় আছে কিlist2 পাশাপাশি সুসংগত (তাই আমি বলতে পারি আইটেমটি 4জন্যে 'three')? সুতরাং, প্রত্যাশিত আউটপুট হবে:

list1 = [1, 1, 2, 3, 4]
list2 = ['one', 'one2', 'two', 'three', 'four']

আমার সমস্যাটি হ'ল আমার কাছে একটি জটিল জটিল প্রোগ্রাম রয়েছে যা তালিকাগুলির সাথে ভাল কাজ করছে তবে আমার কিছু ধরণের ডেটা উল্লেখ করা দরকার start আমি জানি এটি অভিধানগুলির জন্য একটি নিখুঁত পরিস্থিতি তবে আমি আমার প্রসেসিংয়ে অভিধানগুলি এড়ানোর চেষ্টা করছি কারণ মূল কীগুলি মান সারণি করতে হবে (যদি আমি অভিধানগুলি ব্যবহার করতে পারি তবে সেগুলি কীভাবে ব্যবহার করতে হয় তা আমি জানি)।

মূলত এই প্রোগ্রামটির প্রকৃতিটি হ'ল, ডেটাটি এলোমেলো ক্রমে আসে (উপরের মতো), আমাকে এটি বাছাই করা দরকার, এটি প্রক্রিয়া করতে হবে এবং তারপরে ফলাফলগুলি প্রেরণ করতে হবে (অর্ডার কোনও বিষয় নয় তবে ব্যবহারকারীদের জানা দরকার কোন ফলাফলটি কোনটির সাথে সম্পর্কিত চাবি). আমি প্রথমে এটি অভিধানে রাখার বিষয়ে চিন্তা করেছি, তারপরে একটি তালিকা বাছাই করে তবে ক্রম বজায় না রাখলে একই মান সহ আইটেমগুলির মধ্যে আলাদা করার কোনও উপায় আমার কাছে নেই (ফলাফলগুলি ব্যবহারকারীদের সাথে যোগাযোগ করার সময় এর প্রভাব পড়তে পারে)। সুতরাং আদর্শগতভাবে, আমি একবার তালিকাগুলি পেলে উভয় তালিকাকে একসাথে বাছাই করার উপায়টি বুঝি। এটা কি সম্ভব?


আমার উল্লেখ করা উচিত যে তালিকা 2-এ আপনার ভেরিয়েবলগুলি তালিকা 1 এর ইনটগুলিতে নির্দেশ করবে না। উদাহরণস্বরূপ, যদি তালিকা 1 [0] = 9 এর মতো মান পরিবর্তন করে এবং তালিকা 2 দেখুন, তালিকা 2 [0] এখনও 3 হবে। পাইথনের পূর্ণসংখ্যার সাথে, এটি রেফারেন্স / পয়েন্টার ব্যবহার করে না, এটি মানটি অনুলিপি করে। আপনি তালিকা 2 = list1 [:]
রবার্ট কিং

উত্তর:


242

এই সমস্যার এক ক্লাসিক পদ্ধতির মধ্যে রয়েছে "সাজসজ্জা, সাজান, উপজাতি" আইডিয়ামটি ব্যবহার করা যা বিশেষত পাইথনের বিল্ট-ইন zipফাংশনটি ব্যবহার করে সহজ :

>>> list1 = [3,2,4,1, 1]
>>> list2 = ['three', 'two', 'four', 'one', 'one2']
>>> list1, list2 = zip(*sorted(zip(list1, list2)))
>>> list1
(1, 1, 2, 3, 4)
>>> list2 
('one', 'one2', 'two', 'three', 'four')

এগুলি অবশ্যই আর তালিকাগুলি নয়, তবে এটি সহজেই প্রতিকার পায়, যদি এটি গুরুত্বপূর্ণ হয়:

>>> list1, list2 = (list(t) for t in zip(*sorted(zip(list1, list2))))
>>> list1
[1, 1, 2, 3, 4]
>>> list2
['one', 'one2', 'two', 'three', 'four']

এটি লক্ষণীয় যে উপরেরগুলি নির্গমনতার জন্য গতি ত্যাগ করতে পারে; ইন-প্লেস সংস্করণ, যা 3 টি লাইন নিয়েছে, ছোট তালিকার জন্য আমার মেশিনে দ্রুত এগিয়ে চলেছে:

>>> %timeit zip(*sorted(zip(list1, list2)))
100000 loops, best of 3: 3.3 us per loop
>>> %timeit tups = zip(list1, list2); tups.sort(); zip(*tups)
100000 loops, best of 3: 2.84 us per loop

অন্যদিকে, বৃহত তালিকার জন্য, এক-লাইনের সংস্করণটি দ্রুততর হতে পারে:

>>> %timeit zip(*sorted(zip(list1, list2)))
100 loops, best of 3: 8.09 ms per loop
>>> %timeit tups = zip(list1, list2); tups.sort(); zip(*tups)
100 loops, best of 3: 8.51 ms per loop

কোয়ান্টাম points হিসাবে উল্লেখ করা হয়েছে, জেএসএফের পরামর্শটি এখনও কিছুটা দ্রুত, তবে এটি সম্ভবত কিছুটা দ্রুত হবে কারণ পাইথন সমস্ত কী-ভিত্তিক প্রকারের জন্য অভ্যন্তরীণভাবে একই ডিএসইউ আইডিয়মটি ব্যবহার করে। এটি কেবল খালি ধাতুর কাছাকাছি ঘটছে। (এটি দেখায় যে zipরুটিনগুলি কতটা অনুকূলিত হয়েছে !)

আমি মনে করি zipভিত্তিক পদ্ধতিটি আরও নমনীয় এবং কিছুটা বেশি পঠনযোগ্য, তাই আমি এটিকে পছন্দ করি।


6
তৃতীয় লাইনের নক্ষত্রটি কী উপস্থাপন করে?
জেফ্রি


1
জেএফ সেবাস্তিয়ান প্রস্তাবিত বাছাই করা সূচক / মানচিত্রের দৃষ্টান্তটি আমার জন্য জিপ সমাধানের চেয়ে প্রায় 10% দ্রুত (10000 এলোমেলো অন্তর্নিহিত তালিকা ব্যবহার করে):% টাইমিট সূচক = পরিসর (লেন (এল 1)); index.sort (কী = L1 .__ getitem__); মানচিত্র (l1 .__ getitem__, সূচক); মানচিত্র (l2 .__ getitem__, সূচক) 100 লুপ, প্রতি লুপে 3: 8.04 এমএসের সেরা (বনাম 9.17 এমএস, প্রেরকের সময়সীমার 9.07 এমএস)
কোয়ান্টাম 7

1
তালিকা 1 এর প্রথম এবং দ্বিতীয় জিপ, তালিকা 2 = জিপ (* বাছাই করা (জিপ (তালিকা 1, তালিকা 2)) বিভিন্ন ধরণের কাজ করে। * সমস্ত পার্থক্য করে।
আশু

1
@ আশু, এক অর্থে, হ্যাঁ! তবে অন্য অর্থে এগুলি মোটেই আলাদা। zip(*x)আকর্ষণীয় সম্পত্তি এটি এটি নিজস্ব বিপরীত: l = [(1, 2), (3, 4)]; list(zip(*zip(*l))) == lফেরত দেয় True। এটি কার্যকরভাবে একটি স্থানান্তর অপারেটর। zip()নিজে থেকে কেবল একই অপারেটর, তবে ধরে নেওয়া হয় যে আপনি ম্যানুয়ালি ইনপুট ক্রমটি প্যাক করেছেন।
প্রেরক

30

আপনি কী হিসাবে মানগুলি ব্যবহার করে সূচকগুলি বাছাই করতে পারেন:

indexes = range(len(list1))
indexes.sort(key=list1.__getitem__)

সাজানো সূচী অনুসারে বাছাই করা তালিকা পেতে:

sorted_list1 = map(list1.__getitem__, indexes)
sorted_list2 = map(list2.__getitem__, indexes)

আপনার ক্ষেত্রে আপনার থাকা উচিত নয় list1, list2বরং জোড়াগুলির একটি একক তালিকা:

data = [(3, 'three'), (2, 'two'), (4, 'four'), (1, 'one'), (1, 'one2')]

এটি তৈরি করা সহজ; পাইথনে বাছাই করা সহজ:

data.sort() # sort using a pair as a key

কেবল প্রথম মান অনুসারে বাছাই করুন:

data.sort(key=lambda pair: pair[0])

এটি সম্পর্কে দুর্দান্ত জিনিস হ'ল আমি সূচিগুলি চারপাশে রাখতে পারি এবং পরে অন্যান্য জিনিসগুলি সাজিয়ে রাখতে পারি, ক্ষেত্রে তালিকা 1 একটি গুরুত্বপূর্ণ সমন্বয় যা বিভিন্ন অন্যান্য অ্যারেগুলিকে প্রভাবিত করে।
EL_DON

3
সূচকগুলি = অজগর 3 এর জন্য তালিকা (পরিসীমা (লেন (তালিকা 1))
ডোনকুইকং

@ ডনকুইকং-এও আপনাকে list() চারপাশে দরকার map()যদি আপনি পাইথন ৩
jfs

বা, পরিবর্তে এক sorted_list1 = list(map(list1.__getitem__, indexes))করতে পারে sorted_list1 = [list1[i] for i in indexes]
নাথান

20

আমি আবিষ্কার না করা অবধি দীর্ঘকাল ধরে প্রেরকের দেওয়া উত্তরটি ব্যবহার করেছি np.argsort। এটা যেভাবে কাজ করে।

# idx works on np.array and not lists.
list1 = np.array([3,2,4,1])
list2 = np.array(["three","two","four","one"])
idx   = np.argsort(list1)

list1 = np.array(list1)[idx]
list2 = np.array(list2)[idx]

আমি এই সমাধানটিকে আরও স্বজ্ঞাত বলে মনে করি এবং এটি সত্যই ভাল কাজ করে। সুগন্ধি:

def sorting(l1, l2):
    # l1 and l2 has to be numpy arrays
    idx = np.argsort(l1)
    return l1[idx], l2[idx]

# list1 and list2 are np.arrays here...
%timeit sorting(list1, list2)
100000 loops, best of 3: 3.53 us per loop

# This works best when the lists are NOT np.array
%timeit zip(*sorted(zip(list1, list2)))
100000 loops, best of 3: 2.41 us per loop

# 0.01us better for np.array (I think this is negligible)
%timeit tups = zip(list1, list2); tups.sort(); zip(*tups)
100000 loops, best for 3 loops: 1.96 us per loop

যদিও np.argsortএটি দ্রুততম নয়, তবে এটি ব্যবহার করা আমার পক্ষে সহজ।


1
আপনার উদাহরণটি চালাতে আমি একটি ত্রুটি TypeError: only integer arrays with one element can be converted to an indexপেয়েছি : (পাইথন ২.7..6, অদ্ভুত 1.8.2)। এটি ঠিক করার জন্য, তালিকা 1 এবং তালিকা 2 অবশ্যই নাম্পার অ্যারে হিসাবে ঘোষণা করতে হবে।
বেনবি

ধন্যবাদ। এই কি আমি ফাংশন মন্তব্য মন্তব্য লিখতে না? যাইহোক, আমি মনে করি এটি নির্বোধ যা অভ্যন্তরীণভাবে np.argsortরূপান্তরিত করার চেষ্টা করে না np.array
ড্যানিয়েল থাগাগার্ড আন্দ্রেসেন

আমি প্রথম কোড স্নিপেটের উল্লেখ করছি যেহেতু এটি লিখিত হিসাবে চলবে না :)
বেনি

আমি তালিকাগুলিকে রূপান্তর করে এটিকে সংশোধন করেছি যখন সেগুলি নাম্বার অ্যারেগুলিতে নির্ধারিত করা হয়। মন্তব্যের জন্য ধন্যবাদ :)
ড্যানিয়েল থাগাগার্ড আন্দ্রেসেন

এখন তারা দুবার নম্পি অ্যারেতে রূপান্তরিত হয়েছে;)
বেনবি

13

রুপান্তর Schwartzian । অন্তর্নির্মিত পাইথন বাছাই স্থিতিশীল, সুতরাং দুটি 1কারণে কোনও সমস্যা সৃষ্টি করে না।

>>> l1 = [3, 2, 4, 1, 1]
>>> l2 = ['three', 'two', 'four', 'one', 'second one']
>>> zip(*sorted(zip(l1, l2)))
[(1, 1, 2, 3, 4), ('one', 'second one', 'two', 'three', 'four')]

2
যাইহোক, যদি আপনি এটি করার দরকার মনে করেন তবে আপনার 2-টি সমান্তরাল "উপাত্তের দুটি সমান্তরাল" তালিকা থাকার বিষয়ে দৃ strongly়ভাবে পুনর্বিবেচনা করা উচিত, 2-টিউপস (জোড়) এর তালিকা রাখার বিপরীতে ... অথবা সম্ভবত বাস্তবে কোনও শ্রেণি তৈরি করা উচিত ।
কার্ল নচেটেল


2

এটি সম্পাদন করতে আপনি zip()এবং sort()কার্যগুলি ব্যবহার করতে পারেন :

Python 2.6.5 (r265:79063, Jun 12 2010, 17:07:01)
[GCC 4.3.4 20090804 (release) 1] on cygwin
>>> list1 = [3,2,4,1,1]
>>> list2 = ['three', 'two', 'four', 'one', 'one2']
>>> zipped = zip(list1, list2)
>>> zipped.sort()
>>> slist1 = [i for (i, s) in zipped]
>>> slist1
[1, 1, 2, 3, 4]
>>> slist2 = [s for (i, s) in zipped]
>>> slist2
['one', 'one2', 'two', 'three', 'four']

আশাকরি এটা সাহায্য করবে


2

তালিকার 2 টিতে একই মান না থাকলে আপনি বাছাই করা () পদ্ধতিতে মূল যুক্তিটি ব্যবহার করতে পারেন।

কোডটি নীচে দেওয়া হল:

sorted(list2, key = lambda x: list1[list2.index(x)]) 

এটি তালিকা 1-এর সাথে সম্পর্কিত মান অনুসারে তালিকা 2 সাজায়, তবে নিশ্চিত হয়ে নিন যে এটি ব্যবহার করার সময়, তালিকা 2-তে কোনও দুটি মান সমান হতে পারে না কারণ list.index () ফাংশনটি প্রথম মান দেয়


সাজানো কিছু পরিস্থিতিতে কিছুটা ধীর হলেও এটি কাজ করে।
tyan

2

একটি উপায় হ'ল পরিচয় অনুসারে বাছাই করে প্রতিটি সূচক কোথায় যায় তা ট্র্যাক করা [0,1,2, .. n]

এটি যে কোনও সংখ্যক তালিকার জন্য কাজ করে।

তারপরে প্রতিটি আইটেমকে তার অবস্থানে নিয়ে যান। স্প্লাইস ব্যবহার করা সবচেয়ে ভাল।

list1 = [3,2,4,1, 1]
list2 = ['three', 'two', 'four', 'one', 'one2']

index = list(range(len(list1)))
print(index)
'[0, 1, 2, 3, 4]'

index.sort(key = list1.__getitem__)
print(index)
'[3, 4, 1, 0, 2]'

list1[:] = [list1[i] for i in index]
list2[:] = [list2[i] for i in index]

print(list1)
print(list2)
'[1, 1, 2, 3, 4]'
"['one', 'one2', 'two', 'three', 'four']"

দ্রষ্টব্য আমরা তালিকাগুলি এমনকি বাছাই না করে পুনরাবৃত্তি করতে পারতাম:

list1_iter = (list1[i] for i in index)

1

আপনি যদি ন্যালি ব্যবহার করছেন তবে আপনি np.argsortবাছাই করা সূচকগুলি পেতে এবং তালিকাতে সেই সূচকগুলি প্রয়োগ করতে পারেন । আপনি যে তালিকাটি বাছাই করতে চান তার জন্য এটি কাজ করে।

import numpy as np

arr1 = np.array([4,3,1,32,21])
arr2 = arr1 * 10
sorted_idxs = np.argsort(arr1)

print(sorted_idxs)
>>> array([2, 1, 0, 4, 3])

print(arr1[sorted_idxs])
>>> array([ 1,  3,  4, 21, 32])

print(arr2[sorted_idxs])
>>> array([ 10,  30,  40, 210, 320])

0

একটি অ্যালগরিদমিক সমাধান:

list1 = [3,2,4,1, 1]
list2 = ['three', 'two', 'four', 'one', 'one2']


lis = [(list1[i], list2[i]) for i in range(len(list1))]
list1.sort()
list2 = [x[1] for i in range(len(list1)) for x in lis if x[0] == i]

আউটপুট: -> আউটপুট গতি: 0.2s

>>>list1
>>>[1, 1, 2, 3, 4]
>>>list2
>>>['one', 'one2', 'two', 'three', 'four']

0

অন্য তালিকার বিপরীতে বাছাই করার সময় স্ট্রিং তালিকার ক্রম ধরে রাখার জন্য অন্য পদ্ধতি:

list1 = [3,2,4,1, 1]
list2 = ['three', 'two', 'four', 'one', 'one2']

# sort on list1 while retaining order of string list
sorted_list1 = [y for _,y in sorted(zip(list1,list2),key=lambda x: x[0])]
sorted_list2 = sorted(list1)

print(sorted_list1)
print(sorted_list2)

আউটপুট

['one', 'one2', 'two', 'three', 'four']
[1, 1, 2, 3, 4]

0

আমি ওপেন জেএফএসের উত্তরটি প্রসারিত করতে চাই যা আমার সমস্যার জন্য দুর্দান্ত কাজ করেছে: দুটি তালিকে তৃতীয়, সাজানো তালিকা অনুসারে বাছাই :

আমরা আমাদের সাজানো তালিকাটি যে কোনও উপায়ে তৈরি করতে পারি, তবে এই ক্ষেত্রে আমরা দুটি মূল তালিকার একটির উপাদান থেকে এটি তৈরি করব, যা আমরা বাছাই করতে চাই:

# say we have the following list and we want to sort both by the algorithms name 
# (if we were to sort by the string_list, it would sort by the numerical 
# value in the strings)
string_list = ["0.123 Algo. XYZ", "0.345 Algo. BCD", "0.987 Algo. ABC"]
dict_list = [{"dict_xyz": "XYZ"}, {"dict_bcd": "BCD"}, {"dict_abc": "ABC"}]

# thus we need to create the decorator list, which we can now use to sort
decorated = [text[6:] for text in string_list]  
# decorated list to sort
>>> decorated
['Algo. XYZ', 'Algo. BCD', 'Algo. ABC']

এখন আমরা আমাদের দুটি তালিকাকে তৃতীয় দ্বারা বাছাই করতে jfs এর সমাধান প্রয়োগ করতে পারি

# create and sort the list of indices
sorted_indices = list(range(len(string_list)))
sorted_indices.sort(key=decorated.__getitem__)

# map sorted indices to the two, original lists
sorted_stringList = list(map(string_list.__getitem__, sorted_indices))
sorted_dictList = list(map(dict_list.__getitem__, sorted_indices))

# output
>>> sorted_stringList
['0.987 Algo. ABC', '0.345 Algo. BCD', '0.123 Algo. XYZ']
>>> sorted_dictList
[{'dict_abc': 'ABC'}, {'dict_bcd': 'BCD'}, {'dict_xyz': 'XYZ'}]

সম্পাদনা: আরে ছেলেরা আমি এ সম্পর্কে একটি ব্লক পোস্ট করেছি, আপনার যদি মনে হয় তবে এটি পরীক্ষা করে দেখুন :) 🐍🐍🐍 🐍🐍🐍


-1
newsource=[];newtarget=[]
for valueT in targetFiles:
    for valueS in sourceFiles:
            l1=len(valueS);l2=len(valueT);
            j=0
            while (j< l1):
                    if (str(valueT) == valueS[j:l1]) :
                            newsource.append(valueS)
                            newtarget.append(valueT)
                    j+=1

2
কয়েক লাইনের ব্যাখ্যা সহায়ক হবে
সাইডমোমেন

@saiedmomen আমি রেফারেন্সের এটা পোস্ট stackoverflow.com/questions/53829160/... এখানে লক্ষ্য স্ট্রিং উৎস স্ট্রিং উপর অনুসন্ধান করা হয়।
ব্যবহারকারী 10340258
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.