पायथन में संख्या और उनके नकारात्मक समकक्षों की सूची बनाएं


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
क्या सकारात्मक संख्याओं को नकारात्मक लोगों से पहले आना चाहिए?
— एरच

2
@ जब तक नहीं, मेरे मामले में आदेश मायने नहीं रखता।
— UPE

6
यदि आदेश कोई मायने नहीं रखता है, तो क्या यह भी एक सूची होने की आवश्यकता है? क्या एक सेट ठीक होगा (जो अनियंत्रित है), या एक जनरेटर या टपल (जो दोनों का आदेश दिया गया है)?
— JG

@ जेजी मैं बाद में एक आंकड़ा बनाना चाहता हूं। माना जाता है कि बिखराव आदि का उपयोग scalar or array-like, shapeकरना तो कोई भी ठीक होगा।
— UPE

2
इनमें से अधिकांश उत्तर कुछ गोल्फ विरोधी समाधानों की तरह पढ़ रहे हैं; छँटाई, जनरेटर कार्य, itertools। मैं बहुत अधिक 'उत्तर' की तुलना में आपके द्वारा प्रदान किए गए कोड को बनाए रखूंगा।
— Peilonrayz

जवाबों:


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 से अधिक लिखें" बनाम "प्रत्येक व्यक्ति के माध्यम से जाएं। ठीक है, क्या वे पुरुष हैं? यदि ऐसा है, तो ..." )। मैं उन्हें इस कारण से उपयोग करता हूं, इसलिए नहीं कि मैं कुछ भी "जैसा दिखने" की कोशिश कर रहा हूं। यदि समस्या है तो लंबी लाइनों को कई लाइनों पर तोड़ा जा सकता है।
— जाज

2
काफी उचित। लेकिन यही वह विषय है जो विषय-वस्तु में आता है: मैं व्यक्तिगत रूप से सूची को कम से कम पठनीय के रूप में मानसिक तनाव के रूप में जनरेटर फ़ंक्शन के रूप में सूची में हल करता हूं । मैं फिर भी नाम बदलने के द्वारा Datanovice के जवाब की पठनीयता (या बल्कि पठनीयता-मेरे लिए) में सुधार yकरेगा signedValue। मेरे लिए डिफाइन-ए-फंक्शन एप्रोच का वास्तविक जोड़ा मूल्य बर्मन के chainएक-लाइनर की समस्या से बचने के लिए (सकारात्मक, तब नकारात्मक) पूछे गए सख्त आदेश में परिणाम देने के लिए होगा जिसमें थोड़ा-अलग संख्यात्मक तर्क होते हैं दो बार हार्ड-कोडित होना।
— १२:०२ बजे jez

2
मैं सूची की समझ के बारे में सामान्य भावना से सहमत हूं, लेकिन इस तरह से एक फ़ंक्शन को परिभाषित करना भी जानने के लिए एक बहुत ही उपयोगी तकनीक है। (यह एक पुनरावर्ती एल्गोरिदम द्वारा पुनरावर्ती जेनरेटर लिखकर listया शीर्ष स्तर के परिणाम को पास करने के लिए या जो भी हो, परिणाम प्राप्त करने के लिए विशेष रूप से शक्तिशाली है । इन निर्णयों को सर्वोत्तम बनाने के लिए कोड करने की कोशिश करने के वर्षों के बाद, एकमात्र सामान्य सिद्धांत जो मुझे समझ में आता है। : यदि कार्यक्रम में कुछ देने के लिए एक स्पष्ट, अच्छा नाम है, तो ऐसा करने का अवसर लें (और फ़ंक्शंस हम ऐसा करने के तरीकों में से एक हैं)।
— कार्ल Knechtel

42

मैं कहता हूं कि सरलतम समाधान दो श्रेणियों को *अनपैकिंग ऑपरेटर का उपयोग करके सूची में अनपैक करना है:

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

न केवल यह अभी तक का सबसे छोटा उत्तर है, यह सबसे अधिक प्रदर्शन करने वाला भी है, क्योंकि यह केवल एक सूची का निर्माण करता है और इसमें दो rangeएस से परे कोई फ़ंक्शन कॉल शामिल नहीं है ।

मैंने timeitमॉड्यूल का उपयोग करके इस प्रश्न के सभी उत्तरों का परीक्षण करके इसे सत्यापित किया :

उत्तर आईडी विधि समय परिणाम
-------------------------------------------------- ------------------------------------------------
(प्रश्न में) [x के लिए x सीमा में (6,10)] + [y में y के लिए सीमा (-9, -5)] 0.843 प्रति लूप usec
(यह उत्तर) [* रेंज (6, 10), * रेंज (-9, -5)] 0.509 usec प्रति लूप
61348876 [y में x के लिए रेंज (6,10) में y के लिए (x, -x)] 0.754 हमारे लूप में
61349149 सूची (रेंज_विथ_नेगेटिव (6, 10)) 0.795 प्रति लूप
61348914 सूची (itertools.chain (रेंज (6, 10), रेंज -9, -5)) प्रति लूप 0.709 usec
61366995 [साइन * x के लिए साइन, x में itertools.product ((- 1, 1), रेंज (6, 10)) 0.899 usec प्रति लूप
61371302 सूची (श्रेणी (6, 10)) + सूची (श्रेणी (-9, -5)) 0.729 usec लूप
61367180 सूची (रेंज_विथ_नेग्स (6, 10)) 1.95 usec प्रति लूप

(मेरे अपने कंप्यूटर पर पायथन परीक्षण 3.6.9 के साथ प्रदर्शन समय (औसत चश्मा))


2
मैं यह मानने के लिए उत्सुक नहीं हूं कि प्रदर्शन तब प्रासंगिक है जब आपके पास <10 आइटम के साथ एक उदाहरण है, लेकिन यह स्पष्ट रूप से सबसे सरल समाधान है।
— जॉलीजोकर

आप हार्डकॉकिंग के बिना नकारात्मक मूल्यों के आरंभ और अंत का पता कैसे लगाते हैं?
— अलदोक्कानी

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 को चर के साथ बदलें)
— Maarten Fabré

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 अधिक तेज है।
— अप्रूवलडार्कनेस

यह एक साफ-सुथरा विचार है, लेकिन शायद समस्या के विवरण के लिए यह बहुत विशिष्ट है। दूसरों द्वारा दी जाने वाली तकनीकें आमतौर पर अधिक लागू होती हैं।
— कार्ल केनचेल

@ApproachingDarknessFish मैं सहमत हूं कि इसे टाला जाना चाहिए 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

IMO का उपयोग करने 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]

अधिक संक्षिप्त है, लेकिन मैं एक त्वरित स्कैन में टपकने के लिए कठिन unpping tuple पाते हैं।


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 बी = 10

nums = [x + y में x के लिए - (- (a + b-1), 0) y के लिए रेंज में (a, b)

परिणाम -9, -8, ..., 8, 9 होना चाहिए।

मेरा मानना ​​है कि अंकों की अभिव्यक्ति में सुधार किया जा सकता है, जो "और" श्रेणी में "इस प्रकार है" अभी भी मुझे असंतुलित दिखता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.