একটি তালিকা থেকে এলোমেলো উপাদান পপ করার জন্য অজগর উপায় কি?


90

বলুন আমার কাছে xঅজানা দৈর্ঘ্যের একটি তালিকা রয়েছে যা থেকে আমি এলোমেলোভাবে একটি উপাদান পপ করতে চাই যাতে তালিকার পরে উপাদানটি না থাকে। এটি করার সর্বাধিক পাইথোনিক উপায় কী?

আমি বরং একটি unhandy combincation ব্যবহার এটা করতে পারেন pop, random.randintএবং len, এবং খাটো বা সুন্দর সমাধান দেখতে চাই:

import random
x = [1,2,3,4,5,6]
x.pop(random.randint(0,len(x)-1))

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

মনে রাখবেন যে আমি পাইথন ২.6 ব্যবহার করছি এবং অনুসন্ধান কার্যের মাধ্যমে কোনও সমাধান পাইনি।


4
আমি পাইথনিস্টার খুব বেশি কিছু নই, তবে নিশ্চিত যে এটি আমার কাছে বেশ সুন্দর দেখাচ্ছে।
ম্যাট বল

একটি বিশদ সময় জটিলতা বিশ্লেষণ আমার দ্বারা সম্পাদিত হয়েছে, রাস্তার নিচে কোথাও আমার উত্তর দেখুন। ঝাঁকুনি কার্যকর না! আপনি যদি কোনওভাবে আইটেমগুলির ক্রম পরিবর্তন করতে চান তবে আপনি এখনও ব্যবহার করতে পারেন। যদি পপ (0) আপনার সম্পর্কে উদ্বেগ প্রকাশ করে তবে আমার বিশ্লেষণে উল্লিখিত ডেকিউ ব্যবহার করুন।
নিখিল স্বামী

ও (2) উত্তর ive জন্য সময় জটিলতা। দ্রুত ব্যবহারের জন্য একটি ফাংশন এ এটি মোড়ানো। দয়া করে নোট করুন যে list.pop (-1) ব্যতীত অন্য কোন list.pop (n) O (n) নেয়।
নিখিল স্বামী

উত্তর:


95

আপনি যেটিকে আপ বলে মনে করছেন তা প্রথম স্থানটিতে খুব অজগর দেখায় না। আপনার তালিকার মাঝখানে থেকে জিনিসগুলি অপসারণ করা উচিত নয়, কারণ আমার জানা সমস্ত পাইথন বাস্তবায়নে তালিকা অ্যারে হিসাবে প্রয়োগ করা হয়, সুতরাং এটি একটি O(n)অপারেশন।

অ্যালগরিদমের অংশ হিসাবে যদি আপনার সত্যিই এই কার্যকারিতাটির প্রয়োজন blistহয় তবে আপনার মাঝামাঝি থেকে দক্ষ মোছার সমর্থন করে এমন একটি ডেটা স্ট্রাকচার পরীক্ষা করা উচিত ।

খাঁটি পাইথন-এ, আপনার যদি বাকী উপাদানগুলির অ্যাক্সেসের প্রয়োজন না হয় তবে আপনি যা করতে পারেন তা হল প্রথমে তালিকাটি বদলানো এবং তারপরে পুনরাবৃত্তি করা:

lst = [1,2,3]
random.shuffle(lst)
for x in lst:
  # ...

আপনার যদি সত্যিই বাকীটি প্রয়োজন (যা কোড গন্ধের কিছুটা, আইএমএইচও) হয় তবে অন্তত আপনি pop()এখন তালিকাটির শেষে থেকে যা করতে পারেন (যা দ্রুত!):

while lst:
  x = lst.pop()
  # do something with the element      

সাধারণভাবে, আপনি যদি পরিবর্তনগুলির স্থিতি (তালিকার সাথে আপনি যেমন করেন) এর পরিবর্তে আরও কার্যকরী শৈলী ব্যবহার করেন তবে আপনি প্রায়শই আপনার প্রোগ্রামগুলি আরও মার্জিতভাবে প্রকাশ করতে পারেন।


4
সুতরাং একটি ভাল (দ্রুত) ধারণা ব্যবহার করা হবে random.shuffle(x)এবং তারপরে x.pop()? বুঝতে পারছি না এই "ফাংশনাল" কীভাবে করবেন?
হেনরিক

4
@ হেনরিক: যদি আপনার দুটি সংগ্রহ থাকে (উদাহরণস্বরূপ, অভিধানের একটি তালিকা এবং এলোমেলো সংখ্যার একটি তালিকা) এবং আপনি একই সময়ে সেগুলি পুনরাবৃত্তি করতে চান তবে আপনি তাদের zip(ডিক, সংখ্যা) জোড়ার তালিকা পেতে পারেন to আপনি একাধিক অভিধান সম্পর্কে কিছু বলেছিলেন যার মধ্যে প্রতিটি আপনি একটি এলোমেলো সংখ্যার সাথে যুক্ত করতে চান। zip
এটির

4
আমি ভোট দেওয়ার সময় আমার একটি পোস্ট যুক্ত করার কথা। এমন সময় আছে যখন আপনাকে তালিকার মাঝখানে থেকে কোনও আইটেম সরিয়ে ফেলতে হবে ... আমাকে এখনই এটি করতে হবে to কোনও পছন্দ নেই: আমার একটি অর্ডার তালিকা রয়েছে, আমাকে মাঝখানে একটি আইটেম সরিয়ে ফেলতে হবে। এটি স্তন্যপান করে, তবে কেবলমাত্র অন্য একটি পছন্দ হ'ল একটি আধা-বিরল ক্রিয়াকলাপের জন্য ভারী কোড রিফ্যাক্টরিং করা। ইস্যুটি [] এর একটি বাস্তবায়নের, যা এই জাতীয় ক্রিয়াকলাপের জন্য দক্ষ হওয়া উচিত, তবে তা নয়।
মার্ক গেরোলিমাটোস

4
@ নিক্লাসবি। ওপি উদাহরণ হিসাবে এলোমেলোভাবে ব্যবহার করছিল (প্রকৃতপক্ষে, এটি ছেড়ে দেওয়া উচিত ছিল, এটি ইস্যুটিকে ক্লাউড করেছিল)। "এটি করবেন না" অপর্যাপ্ত। এর চেয়ে আরও ভাল উত্তর হ'ল একটি পাইথন ডেটা স্ট্রাকচারের পরামর্শ দেওয়া উচিত যা SUFFICIENT অ্যাক্সেসের গতি সরবরাহ করার সময় এই ধরনের ক্রিয়াকলাপগুলিকে সমর্থন করে (স্পষ্টভাবে আরার ... এর ... তালিকা হিসাবে ভাল নয়)। অজগর 2 তে, আমি একটিও পাইনি। আমি যদি তা করি তবে আমি তার উত্তর দিয়ে দেব। নোট করুন যে কোনও ব্রাউজারের দুর্ঘটনার কারণে, আমি আমার মূল মন্তব্যে এটি যোগ করতে পারিনি, আমার উচিত ছিল একটি দ্বিতীয় মন্তব্য have আমাকে সৎ রাখার জন্য আপনাকে ধন্যবাদ :)
মার্ক গেরোলিমাটোস

4
@ মার্কগেরোলিমেটস স্ট্যান্ডার্ড লাইব্রেরিতে দক্ষ এলোমেলো অ্যাক্সেস এবং সন্নিবেশ / মোছার উভয়ের সাথে কোনও ডেটা কাঠামো নেই। আপনি সম্ভবত পাইপি.পিথোন.আর.পিপি / বিলিস্টের মতো কিছু ব্যবহার করতে চান আমি এখনও তর্ক করব যে প্রচুর ব্যবহারের ক্ষেত্রে এটি এড়ানো যায়
নিক্লাস বি।

51

আপনি এর চেয়ে আরও ভাল কিছু পাবেন না, তবে এখানে সামান্য উন্নতি হবে:

x.pop(random.randrange(len(x)))

ডকুমেন্টেশন এতে random.randrange():

random.randrange ([শুরু], থামান [, পদক্ষেপ])
এলোমেলোভাবে নির্বাচিত উপাদানটি থেকে ফিরে আসুন range(start, stop, step)। এটি সমতুল্য choice(range(start, stop, step)), তবে বাস্তবে কোনও পরিসীমা অবজেক্ট তৈরি করে না।


14

বাকী তালিকার উপাদানগুলির ক্রম যদি বিবেচনা না করে তবে তালিকা থেকে এলোমেলো সূচীতে একটি একক উপাদান অপসারণ করতে :

import random

L = [1,2,3,4,5,6]
i = random.randrange(len(L)) # get random index
L[i], L[-1] = L[-1], L[i]    # swap with the last element
x = L.pop()                  # pop last element O(1)

তালিকাটির মাঝামাঝি থেকে মুছে ফেলার ক্ষেত্রে ও (এন) এর আচরণ এড়ানোর জন্য অদলবদল ব্যবহৃত হয়।


9

এখানে অন্য বিকল্পটি রয়েছে: আপনি কেন প্রথমে তালিকাটি রদবদল করবেন না এবং তারপরে আর কোনও উপাদান না থাকা পর্যন্ত এর উপাদানগুলি পপিং শুরু করবেন না? এটার মত:

import random

x = [1,2,3,4,5,6]
random.shuffle(x)

while x:
    p = x.pop()
    # do your stuff with p

4
@ নিক্লাসবি। কারণ আমরা তালিকা থেকে উপাদানগুলি অপসারণ করছি। যদি উপাদানগুলি অপসারণ করা একেবারে প্রয়োজনীয় না হয় তবে হ্যাঁ আমি আপনার সাথে একমত:[for p in x]
এসকর লোপেজ

কারণ এটি তালিকাকে পরিবর্তিত করে এবং আপনি যদি এখন থেকে অর্ধেক উপাদান এবং এখন অর্ধেক অংশ বেছে নিতে চান তবে আপনার অবশিষ্ট সেটটি পরে থাকবে।
হেনরিক

@ হেনরিক: ঠিক আছে, এ কারণেই আমি আপনাকে জিজ্ঞাসা করেছি যে আপনার যদি বাকি তালিকা দরকার হয়। আপনি যে উত্তর দেয় নি।
নিক্লাস বি।

2

এটি করার একটি উপায়:

x.remove(random.choice(x))

7
যদি উপাদানগুলি একবারে আরও ঘটে তবে এটি সমস্যাযুক্ত হতে পারে।
নিক্লাস বি।

4
ডুপ্লিকেট থাকা অবস্থায় এটি বামতম উপাদানটি সরিয়ে ফেলবে, পুরোপুরি এলোমেলো ফলাফলের কারণ হবে না।
ফোগলবার্ড

সঙ্গে popএই তুমি পারবে না সরানো উপাদান এ একটি নাম বাতলান করতে পারেন।
agf

যথেষ্ট উপযুক্ত, আমি সম্মত হই যে যখন উপাদানগুলি একাধিকবার ঘটে থাকে তখন এটি খুব এলোমেলো নয়।
শিমোন ভিজার 19

4
আপনার বিতরণ স্কিওয়ের প্রশ্নটি বাদ removeদিয়ে তালিকার একটি লিনিয়ার স্ক্যান প্রয়োজন। সূচকের সন্ধানের তুলনায় এটি মারাত্মকভাবে অক্ষম।
অ্যারোনস্টার্লিং

2

তালিকা থেকে পপিংয়ের সময়, নকল ছাড়াই একটি তালিকা থেকে এক্স এলোমেলো আইটেমগুলি পাওয়ার চেষ্টা করার সময় আমি গুগলে এই প্রশ্নের মুখোমুখি হয়েছি। অবশেষে আমি যা ব্যবহার করেছি তা এখানে:

items = [1, 2, 3, 4, 5]
items_needed = 2
from random import shuffle
shuffle(items)
for item in items[:items_needed]:
    print(item)

আপনি যদি একটি সম্পূর্ণ তালিকাটি পরিবর্তন করে চলেছেন তবে কেবলমাত্র এটির একটি ছোট অংশ ব্যবহার করছেন এটি কিছুটা অক্ষম হতে পারে তবে আমি কোনও অপ্টিমাইজেশান বিশেষজ্ঞ নই যাতে আমার ভুল হতে পারে।


4
random.sample(items, items_needed)
jfs

2

আমি জানি এটি একটি পুরানো প্রশ্ন, তবে কেবল নথিপত্রের জন্য:

যদি আপনি (একই প্রশ্নটি গুগল করছেন এমন ব্যক্তি) আপনি যা করছেন বলে মনে করছেন আপনি যা করছেন, যা কোনও তালিকা থেকে এলোমেলোভাবে k সংখ্যার আইটেম নির্বাচন করছে (যেখানে কে <= লেন (আপনার তালিকা)) তবে নিশ্চিত করে নিন যে প্রতিটি আইটেম আর কখনও নির্বাচিত হবে না making এক সময়ের চেয়ে (= প্রতিস্থাপন ছাড়াই নমুনা), আপনি এলোমেলোভাবে ব্যবহার করতে পারেন @ @ jf -sebastian পরামর্শ মতো নমুনা । তবে ব্যবহারের কেস সম্পর্কে আরও না জেনে, আপনার যা প্রয়োজন তা আমি জানি না।


2

অনেক উত্তর সত্ত্বেও ব্যবহারের পরামর্শ দেয় random.shuffle(x)এবং x.pop()এটি বড় ডেটাতে খুব ধীর হয়। এবং 10000উপাদানগুলির তালিকার জন্য প্রয়োজনীয় 6 secondsসময়গুলি যখন বদলাতে সক্ষম করা সক্ষম হয় took যখন বদল অক্ষম করা হয় তখন গতি ছিল0.2s

উপরে প্রদত্ত সমস্ত পদ্ধতি পরীক্ষার পরে দ্রুততম পদ্ধতিটি @jfs দ্বারা লিখিত প্রমাণিত হয়েছিল

import random

L = ['1',2,3,'4'...1000] #you can take mixed or pure list
i = random.randrange(len(L)) # get random index
L[i], L[-1] = L[-1], L[i]    # swap with the last element
x = L.pop()                  # pop last element O(1)

আমার দাবির সমর্থনে এই উত্স থেকে সময় জটিলতা চার্ট এখানে চিত্র বর্ণনা লিখুন


যদি তালিকায় কোনও সদৃশ না থাকে,

আপনি সেটগুলি ব্যবহার করে আপনার উদ্দেশ্য অর্জন করতে পারেন। সেট ডুপ্লিকেটগুলিতে তৈরি তালিকাটি সরানো হবে। remove by valueএবং remove randomব্যয় O(1), খুব কার্যকর। এই আমি সবচেয়ে পরিষ্কার পদ্ধতি সঙ্গে আসতে পারে।

L=set([1,2,3,4,5,6...]) #directly input the list to inbuilt function set()
while 1:
    r=L.pop()
    #do something with r , r is random element of initial list L.

ভিন্ন listsযা সমর্থন A+Bবিকল্প, setsএছাড়াও সমর্থন A-B (A minus B)সহ A+B (A union B)এবংA.intersection(B,C,D) । যখন আপনি ডেটাতে লজিকাল অপারেশন করতে চান তখন সুপার দরকারী।


বিকল্প

আপনি যদি গতি পেতে চান তবে তালিকার মাথার এবং লেজের উপর ক্রিয়াকলাপ সম্পাদিত হয়, আমার দাবির সমর্থনে পাইথন ডেকিউ (ডাবল এন্ড কুই) ব্যবহার করুন এখানে চিত্র। একটি চিত্র হাজার শব্দ।

এখানে চিত্র বর্ণনা লিখুন


1

এই উত্তরটি আসে @ নিকলাস-বি এর সৌজন্যে :

" আপনি সম্ভবত পাইপি.পিথোন.আর.পি.পি.আই.পি. / লিস্টের মতো কিছু ব্যবহার করতে চান "

পিওয়াইপি পৃষ্ঠাটি উদ্ধৃত করতে :

... ছোট তালিকাতে আরও ভাল অ্যাসিম্পটিক পারফরম্যান্স এবং অনুরূপ কর্মক্ষমতা সহ একটি তালিকার মতো ধরণের

ব্লিস্টটি পাইথন তালিকার জন্য একটি ড্রপ-ইন প্রতিস্থাপন যা বড় তালিকাগুলি সংশোধন করার সময় আরও ভাল পারফরম্যান্স সরবরাহ করে। ব্লিস্ট প্যাকেজটি বাছাই করা তালিকা, বাছাই করা সেট, দুর্বলতা তালিকা, দুর্বলকৃত সেট, বাছাই করা নকশা এবং বিটুপল প্রকারগুলিও সরবরাহ করে।

এটি এলোমেলো অ্যাক্সেস / এলোমেলো রান এন্ডে নিম্নচরিত কার্যকারিতা গ্রহণ করবে , কারণ এটি "লেখার অনুলিপি" ডেটা কাঠামো। এটি পাইথন তালিকায় অনেকগুলি ব্যবহারের ক্ষেত্রে অনুমানকে লঙ্ঘন করে, তাই এটি যত্ন সহ ব্যবহার করুন

যাইহোক, যদি আপনার প্রধান ব্যবহারের ক্ষেত্রে কোনও তালিকা দিয়ে অদ্ভুত এবং অপ্রাকৃত কিছু করা হয় (যেমন @ ওপিতে দেওয়া জোর উদাহরণ হিসাবে, বা আমার পাইথন ২.6 ফিফোর সারি-সহ-পাস ইস্যু), তবে এটি বিলটি সুন্দরভাবে ফিট করবে ।

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