পাইথনে সংখ্যার তালিকা এবং তাদের নেতিবাচক অংশগুলি তৈরি করুন


31

পাইথনে সংখ্যার একটি তালিকা এবং তাদের নেতিবাচক অংশগুলির তৈরি করার জন্য কি কোনও সুবিধাজনক ওয়ান-লাইনার রয়েছে?

উদাহরণস্বরূপ, বলুন আমি 6 থেকে 9 এবং -6 থেকে -9 নম্বর সহ একটি তালিকা তৈরি করতে চাই।

আমার বর্তমান পদ্ধতিটি হ'ল:

l = [x for x in range(6,10)]
l += [-x for x in l]

একটি সাধারণ "ওয়ান-লাইনার" হ'ল:

l = [x for x in range(6,10)] + [y for y in range(-9, -5)]

তবে দুটি তালিকা তৈরি করা এবং তারপরে তাদের সাথে যোগ দেওয়া অসুবিধাজনক বলে মনে হচ্ছে।


3
Theণাত্মক সংখ্যাগুলির আগে ইতিবাচক সংখ্যাগুলি আসা উচিত?
এরিচ

2
@ এরিচ না, অর্ডারটি আমার ক্ষেত্রে কিছু যায় আসে না।
17

6
যদি অর্ডারটি কোনও ব্যাপার না, তবে এটির কি তালিকার তালিকা থাকাও দরকার? একটি সেট কি ঠিক আছে (যা অর্ডারড নয়), বা জেনারেটর বা টিপল (উভয়কেই আদেশ দেওয়া হয়েছে)?
জেজি

@ জিজি আমি পরে একটি চিত্র তৈরি করতে চাই। মনে করা যায় স্ক্যাটার ইত্যাদি ব্যবহার করে তাই যেকোনও scalar or array-like, shapeঠিক আছে।
উপে

2
এই উত্তরগুলির বেশিরভাগগুলি অ্যান্টি-গল্ফ সমাধানগুলির মতো পড়ছে; বাছাই, জেনারেটরের ফাংশন, ইটারলগুলি। আমি বেশিরভাগ 'উত্তর' এর চেয়ে আপনার দেওয়া কোডটি বজায় রাখতে চাই।
পিলোনরেজ

উত্তর:


44

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

nums = [y for x in range(6,10) for y in (x,-x)]
print(nums)
[6, -6, 7, -7, 8, -8, 9, -9]

50

একটি সুন্দর এবং পঠনযোগ্য ফাংশন তৈরি করুন:

def range_with_negatives(start, end):
    for x in range(start, end):
        yield x
        yield -x

ব্যবহার:

list(range_with_negatives(6, 10))

এভাবেই আপনি যে কোনও কিছুর জন্য সুবিধাজনক ওয়ান-লাইনার পান। ম্যাজিক প্রো হ্যাকারের মতো দেখার চেষ্টা করা থেকে বিরত থাকুন।


20
তালিকা / ডিক বোঝার বিরুদ্ধে কুসংস্কারের বিষয়টি এসও তে বেশ সাধারণ এবং এগুলি "পাঠযোগ্য" না বলে সাধারণত এটি ন্যায়সঙ্গত হয়। কোনও নির্মাণের অন্তর্নিহিত পাঠযোগ্যতা ( এটি কীভাবে ব্যবহার করা হয় তার চেয়ে বেশি করে ) মূলত বিষয়ভিত্তিক। ব্যক্তিগতভাবে আমি বোধগম্যগুলি আরও পঠনযোগ্য এবং এই সমাধানটি খুব কম খুঁজে পেয়েছি (তুলনা করুন: "50 বছরের বেশি বয়সী প্রতিটি পুরুষের রক্তচাপ লিখুন" বনাম "প্রতিটি ব্যক্তির মধ্য দিয়ে যান OK ঠিক আছে, তারা কি পুরুষ? যদি তাই হয় তবে ..." )। আমি এগুলি এ কারণে ব্যবহার করি, কারণ আমি কোনও কিছুর "চেহারা" দেওয়ার চেষ্টা করছি না। যদি সমস্যা হয় তবে একাধিক লাইনে দীর্ঘ বোঝাপড়াগুলি ভেঙে দেওয়া যায়।
জিজ

2
যথেষ্ট ফর্সা। কিন্তু যে যেখানে আত্মনিষ্ঠা আসে দেওয়া হল: আমি ব্যক্তিগতভাবে কি পাঠযোগ্য হিসাবে কমপক্ষে তালিকা Comp সমাধান খুঁজে, মানসিক স্ট্রেন পরিপ্রেক্ষিতে জেনারেটর ফাংশন হিসাবে। আমি অবশ্য পুনঃনামকরনের দ্বারা Datanovice এর উত্তর (পাঠযোগ্যতা-জন্য-আমাকে বরং বা,) পাঠযোগ্যতা উন্নতি হবে yথেকে signedValue। আমার কাছে সংজ্ঞায়িত-ফাংশন পদ্ধতির আসল যুক্ত মূল্য হ'ল বার্মারের chainওয়ান-লাইনারের সমস্যাটিকে এড়িয়ে যাওয়ার সময় প্রশ্নটি (ইতিবাচক, তারপর নেতিবাচক) জিজ্ঞাসা করা কঠোর ক্রমে ফলাফল প্রদান করা হবে যেখানে সামান্য-পৃথক সংখ্যাসূচক যুক্তি রয়েছে দুবার হার্ড কোডিং করা।
jez

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

42

আমি বলব যে সরল সমাধান হ'ল *আনপ্যাকিং অপারেটরটি ব্যবহার করে একটি তালিকাতে দুটি রেঞ্জ আনপ্যাক করা :

>>> [*range(6, 10), *range(-9, -5)]
[6, 7, 8, 9, -9, -8, -7, -6]

এটি কেবলমাত্র এই সংক্ষিপ্ত উত্তরটি এখনও প্রস্তাবিত নয়, এটি সর্বাধিক পারফরম্যান্সও, কারণ এটি কেবলমাত্র একটি তালিকা তৈরি করে এবং এতে দুটি কার্যের বাইরে কোনও ফাংশন কল জড়িত না range

আমি timeitমডিউলটি ব্যবহার করে এই প্রশ্নের উত্তরগুলির সবগুলি পরীক্ষা করে যাচাই করেছি :

উত্তর আইডি পদ্ধতি সময়কালীন ফলাফল
-------------------------------------------------- ------------------------------------------------
(প্রশ্নে) [এক্স x রেঞ্জের জন্য (6,10)] + [y এর জন্য রেঞ্জের জন্য (-9, -5)] প্রতি লুপে 0.843 ইউএসসি
(এই উত্তর) [* পরিসীমা (6, 10), * পরিসর (-9, -5)] প্রতি লুপ 0.509 ইউএসি
61348876 [এক্স এর জন্য পরিসীমা জন্য (6,10) y এর জন্য (x, -x)] প্রতি লুপে 0.754 ইউজেক
61349149 তালিকা (রেঞ্জ_উইট_নেগভেটিভস (6, 10%) 0.795 ইউএসসি লুপ প্রতি
61348914 তালিকা (itertools.chain (পরিসর (6, 10), পরিসীমা (-9, -5))) প্রতি লুপ 0.709 ইউএসসি
61366995 [সাইন জন্য এক্স সাইন ইন, ইটারটোউলস এক্স প্রডাক্টে এক্স ((- 1, 1), পরিসীমা (6, 10%)]] প্রতি লুপ 0.899 ইউআরসি
61371302 তালিকা (পরিসীমা (6, 10)) + তালিকা (পরিসীমা (-9, -5)) প্রতি লুপ 0.729 ইউএসসি
61367180 তালিকা (রেঞ্জ_উইথ_নেগস (6, 10%) প্রতি লুপ 1.95 ইউএসসি)

(টাইমিট টেস্টিংটি আমার নিজের কম্পিউটারে পাইথন ৩.6.৯ দিয়ে সঞ্চালিত হয়েছে (গড় চশমা))


2
আপনার কাছে <10 আইটেমের সাথে উদাহরণ থাকা অবস্থায় পারফরম্যান্স প্রাসঙ্গিক বলে ধরে নিতে আমি খুব আগ্রহী নই তবে এটি স্পষ্টতই সহজ সমাধান।
জলি জোকার

নেতিবাচক মানগুলির হার্ডকোডিং না করে আপনি কীভাবে শুরু এবং শেষটি আবিষ্কার করবেন?
aldokkani

1
@aldokkani[*range(x, y), *range(-y + 1, -x + 1)]
RoadrunnerWMC

20

আপনি itertools.chain()দুটি ব্যাপ্তি একত্রিত করতে ব্যবহার করতে পারেন ।

import itertools
list(itertools.chain(range(6, 10), range(-9, -5)))

1
অর্ডারের স্পষ্টত্বে কিছু আসে যায় না এর জন্য আমি 'রেঞ্জ (-6, -10, -1)' ব্যবহার করবো (এবং 6 এবং 10 এর সাথে ভেরিয়েবলগুলি প্রতিস্থাপন করুন)
মার্টেন ফ্যাব্রে

7

আপনি ব্যবহার করতে পারেন itertools.product, যা কার্তেসিয়ান পণ্য।

[sign*x for sign, x in product((-1, 1), range(6, 10))]
[-6, -7, -8, -9, 6, 7, 8, 9]

এটি ধীর হতে পারে কারণ আপনি গুণটি ব্যবহার করেন তবে এটি পড়ার পক্ষে সহজ হওয়া উচিত।

আপনি যদি খাঁটি কার্যকরী সমাধান চান তবে আপনি আমদানি করতে পারেন itertools.starmapএবং operator.mul:

from itertools import product, starmap
from operator import mul

list(starmap(mul, product((-1, 1), range(6, 10))))

তবে এটি কম পাঠযোগ্য।


5
আমি ব্যবহার খুঁজে product, starmapএবং opertaor.mulনেস্টেড তালিকা comprehensions তুলনায় অকারণে ভোঁতা, কিন্তু আমি গুণ ব্যবহারের পরামর্শ অনুমোদন দিতে পারেন। [x * sign for sign in (1, -1) for x in range(6, 10)]তুলনায় মাত্র 10% ধীরে ধীরে [y for x in range(6, 10) for y in (x, -x)]এবং অর্ডার সম্পর্কিত ক্ষেত্রে, টিপল-ভিত্তিক পদ্ধতির বাছাই করার চেয়ে 3x দ্রুত গতিতে আরও দ্রুত।
ডার্কনেসফিশ

এটি একটি ঝরঝরে ধারণা, তবে সমস্যাটির বিশদটির সাথে সম্ভবত খানিকটা নির্দিষ্ট। অন্যদের দেওয়া কৌশলগুলি আরও সাধারণভাবে প্রয়োগ হয়।
কার্ল নচেটেল

@ অ্যাপোরিচিং ডার্কনেসফিশ আমি এটির সাথে একমত starmapএবং mulএড়ানো উচিত, তবে আমি মনে করি productএটি এটিকে আরও পঠনযোগ্য করে তোলে, কারণ এটি পুনরাবৃত্তিকারী এবং তাদের উপাদানগুলিকে পৃথকভাবে ভাগ করে দেয়। তাদের অপ্রত্যাশিত আদেশের কারণে তালিকার বোধগম্যতে ডাবল লুপগুলি বিভ্রান্তিকর হতে পারে।
ফ্র্যাঙ্ক ভেল

4

দুটি rangeবস্তুর সংমিশ্রণের সাথে আপনি সত্যিই কাছাকাছি । তবে এটি করার একটি সহজ উপায় রয়েছে:

>>> list(range(6, 10)) + list(range(-9, -5))
[6, 7, 8, 9, -9, -8, -7, -6]

এটি হ'ল প্রতিটি rangeবস্তুকে একটি তালিকায় রূপান্তর করুন এবং তারপরে দুটি তালিকাকে সংযুক্ত করুন।

আর্ট্রোলগুলি ব্যবহার করে অন্য পদ্ধতি:

>>> list(itertools.chain(range(6, 10), range(-9, -5)))
[6, 7, 8, 9, -9, -8, -7, -6]

itertools.chain()একটি জেনারেলাইজের মতো +: দুটি তালিকাগুলি যুক্ত করার পরিবর্তে এটি "সুপার-ইটারেটর" তৈরির জন্য একের পর এক আইট্রেটর বেঁধে রাখে। তারপরে এটি পাস করুন list()এবং আপনি মেমরিতে চান এমন সমস্ত নম্বর সহ একটি কংক্রিটের তালিকা পাবেন।


3
এই উত্তরটি [x for x in ...]আরও ভাল বানানযুক্ত অন্তর্দৃষ্টি জন্য মূল্যবান list(...)
কার্ল নচেটেল

2

আরও একটি সম্ভাবনা নিয়ে ওজন।

আপনি যদি পঠনযোগ্যতা চান তবে আপনার মূল ওয়ান-লাইনারটি বেশ ভাল ছিল, তবে আমি মনে করি নেতিবাচক সীমারেখাগুলি কম স্পষ্ট করার সাথে সাথে আমি পরিসীমাটিকে একইরূপে পরিবর্তন করব।

[x for x in range(6, 10)] + [-x for x in range(6, 10)]

2

itertools.chainঅন্যান্য উত্তরগুলির কয়েকটি উপস্থাপন করে আইএমও পদ্ধতির ব্যবহার করা এ পর্যন্ত উপলব্ধ সরবরাহকারীর মধ্যে অবশ্যই পরিষ্কার।

তবে, যেহেতু আপনার ক্ষেত্রে মানগুলির ক্রম কোনও বিবেচনাধীন নয় , আপনি দুটি স্পষ্ট rangeবস্তুর সংজ্ঞা দিতে এড়াতে পারবেন এবং এভাবে নেতিবাচক rangeসূচকের জন্য প্রয়োজনীয় সমস্ত অফ-বাই-ওয়ান ম্যাথটি এড়িয়ে চলতে পারবেন itertools.chain.from_iterable:

>>> import itertools
>>> list(itertools.chain.from_iterable((x, -x) for x in range(6, 10)))
[6, -6, 7, -7, 8, -8, 9, -9]

ট্যাড ভার্বোস, তবে যথেষ্ট পাঠযোগ্য।

অনুরূপ অন্য অপশনটি হল ট্যাপল / আর্গুমেন্ট প্লেইন সহ আনপ্যাকিং ব্যবহার করা chain:

>>> list(itertools.chain(*((x, -x) for x in range(6, 10))))
[6, -6, 7, -7, 8, -8, 9, -9]

আরও সংক্ষিপ্ত, তবে আমি দ্রুত স্ক্যান করার জন্য টিপলকে আনপ্যাকিং করা আরও শক্ত find


2

এই থিমে একটি পরিবর্তন হয় (দেখুন @Derte Trdelnik এর উত্তর ) দর্শনের নিম্নলিখিত itertoolsযেখানে

পুনরুক্তিকারী বিল্ডিং ব্লকগুলি [...] নিজেরাই বা সংমিশ্রণে দরকারী।

ধারণাটি হ'ল আমরা একটি নতুন ফাংশন সংজ্ঞায়িত করার সময়, আমরা এটি জেনেরিকও করতে পারি:

def interleaved_negatives(it):
    for i in it:
        yield i
        yield -i

এবং এটি একটি নির্দিষ্ট rangeপুনরাবৃত্তির জন্য প্রয়োগ করুন :

list(interleaved_negatives(range(6, 10)))

0

যদি আপনি নির্দিষ্ট করে অর্ডারটি রাখতে চান তবে আপনি পাইথনের বিল্ট-ইন রেঞ্জ জেনারেটরটি শর্তযুক্ত করে ব্যবহার করতে পারেন:

def range_with_negs(start, stop):
    for value in range(-(stop-1), stop):      
        if (value <= -start) or (value >= start):
            yield value

যা আপনাকে আউটপুট দেয়:

In [1]: list(range_with_negs(6, 10))
Out[1]: [-9, -8, -7, -6, 6, 7, 8, 9]

এবং সম্পূর্ণ পরিসরের জন্য শুরু হিসাবে 0 এর সাথেও কাজ করে।


2
এটি বৃহত্তর মানগুলির জন্য খুব অদক্ষ start
সলোমন উকো

0

কাজটি করার বিভিন্ন উপায় থাকতে পারে।

ভেরিয়েবলগুলি দেওয়া হয়েছে: 1. শুরু = 6 2. স্টপ = 10

বিভিন্ন পদ্ধতির জন্য আপনি এটিও চেষ্টা করে দেখতে পারেন:

def mirror_numbers(start,stop):
  if start<stop:
    val=range(start,stop)
    return [j if i < len(val) else -j for i,j in enumerate([x for x in val]*2) ]

mirror_numbers(6,10)

-1

আমি ঠিক যেমন প্রতিসামগ্রী।

a = 6 b = 10

সংখ্যা = [x + y এক্স এর জন্য (- (a + খ -1), 0) y এর জন্য পরিসীমা (ক, খ)]

ফলাফলটি -9, -8, ..., 8, 9 হওয়া উচিত।

আমি বিশ্বাস করি যে সংখ্যার এক্সপ্রেশনটি উন্নত হতে পারে, যা "ইন" এবং "রেঞ্জ" এর পরেও আমার কাছে ভারসাম্যহীন দেখাচ্ছে।

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