एक पंक्ति में सिर और पूंछ


91

क्या पहले तत्व में एक सूची को अनपैक करने का एक पाइथोनिक तरीका है और एक एकल कमांड में "पूंछ" है?

उदाहरण के लिए:

>> head, tail = **some_magic applied to** [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
>> head
1
>>> tail
[1, 2, 3, 5, 8, 13, 21, 34, 55]

9
याद रखें कि पायथन में एकल-लिंक्ड सूची के रूप में सूचियों को लागू नहीं किया गया है, इसलिए यह ऑपरेशन महंगा है (जैसे: पूरी सूची की प्रतिलिपि बनाने की आवश्यकता है)। इस पर निर्भर करते हुए कि आप क्या हासिल करना चाहते हैं, यह समस्या हो सकती है या नहीं। मैं सिर्फ इस बात का उल्लेख कर रहा हूं क्योंकि इस प्रकार की सूची विनाशकारी अक्सर कार्यात्मक भाषाओं में पाई जाती है, जहां यह वास्तव में एक बहुत सस्ता ऑपरेशन है।
निकल्स बी

जवाबों:


191

पायथन 3.x के तहत, आप इसे अच्छी तरह से कर सकते हैं:

>>> head, *tail = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
>>> head
1
>>> tail
[1, 2, 3, 5, 8, 13, 21, 34, 55]

3.x में एक नई सुविधा *ऑपरेटर को अनपैक करने में उपयोग करना है , जिसका अर्थ है कि कोई अतिरिक्त मान। यह पीईपी 3132 में वर्णित है - विस्तारित Iterable अनपैकिंग । यह भी अनुक्रमों ही नहीं, किसी भी चलने पर काम करने का लाभ है।

यह वास्तव में पठनीय भी है ।

पीईपी में वर्णित है, यदि आप 2.x के तहत समकक्ष करना चाहते हैं (संभावित रूप से एक अस्थायी सूची बनाए बिना), तो आपको यह करना होगा:

it = iter(iterable)
head, tail = next(it), list(it)

जैसा कि टिप्पणियों में उल्लेख किया गया है, यह headअपवाद को फेंकने के बजाय डिफ़ॉल्ट मान प्राप्त करने का अवसर भी प्रदान करता है। यदि आप इस व्यवहार को चाहते हैं next(), तो डिफ़ॉल्ट मान के साथ एक वैकल्पिक दूसरा तर्क लेता है, इसलिए यदि कोई मुख्य तत्व नहीं था , तो next(it, None)आपको देगा None

स्वाभाविक रूप से, यदि आप किसी सूची पर काम कर रहे हैं, तो 3.x सिंटैक्स के बिना सबसे आसान तरीका है:

head, tail = seq[0], seq[1:]

1
क्षमा करें, मैंने अप्रतिस्पर्धी शब्द का प्रयोग किया। मेरा मतलब है कि मैं उदाहरण में क्या कहता हूं, वह पहला तत्व के बिना सूची है
जियाकोमो

1
@NikolayFominyh वे दोनों समान हैं - वे दोनों प्रमुख तत्व लेते हैं और पूंछ तत्वों से युक्त एक नई सूची का निर्माण करते हैं। जटिलता में कोई अंतर नहीं। एक अन्य वर्ग टेल ऑपरेशन को आलसी तरीके से लागू __getitem__/ कर सकता है __setitem__, लेकिन अंतर्निहित सूची में नहीं है।
गैरेथ लेटी जूल

2
1M बार करने वाले 800 तत्वों की सूची में, मेरे पास सिर के लिए 2.8 s, * tail = seq solution और केवल 1.8s for head, tail = seq [0], seq [1:] घोल है। सूचियों के लिए स्लाइसिंग अभी भी तेज है।
काबू

2
@CMCDragonkai नहीं, पायथन की मुख्य सूची वर्ग एक सरणी सूची है। यह O (n) होगा क्योंकि इसमें पूंछ को एक नई सूची (एक O (1) सिर के लिए मिलता है) के साथ कॉपी करना शामिल है।
गारेथ लैटी

1
यह अच्छा सिंटेक्स एक और कारण हैpython 3.x
eigenfield

36
>>> mylist = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
>>> head, tail = mylist[0], mylist[1:]
>>> head
1
>>> tail
[1, 2, 3, 5, 8, 13, 21, 34, 55]

9

ओ (1) head,tailऑपरेशन की जटिलता के लिए आपको dequeहालांकि उपयोग करना चाहिए ।

निम्नलिखित तरीके से:

from collections import deque
l = deque([1,2,3,4,5,6,7,8,9])
head, tail = l.popleft(), l

यह उपयोगी है जब आपको सूची के सभी तत्वों के माध्यम से पुनरावृत्त करना होगा। उदाहरण के लिए, भोले विलय में 2 विभाजन विलय के प्रकार में।


ऐसा लगता है कि जैसे कि deque (list_instance) में O (N) जटिलता है। क्या मै गलत हु?
Никита Конин

1
@ НикитаКонин, आप deque निर्माण के बारे में सही हैं। हालांकि, यदि आप पहले तत्व को एक से अधिक बार एक्सेस करना चाहते हैं, तो head, tail = l.popleft(), l~ O (1) है। head, tail = seq[0], seq[1:]है ओ (एन)।
निकोले फोमिनीह

ऐसा लगता है कि आप बस कर सकते हैं head = l.popleft()और tailसिर्फ एक उपनाम है l। अगर lबदलाव tailभी आए।
कोन साइक

2

पैंथन 2, लैम्ब्डा का उपयोग कर

>>> head, tail = (lambda lst: (lst[0], lst[1:]))([1, 1, 2, 3, 5, 8, 13, 21, 34, 55])
>>> head
1
>>> tail
[1, 2, 3, 5, 8, 13, 21, 34, 55]

1
क्यों दुनिया में आप सिर्फ के बजाय ऐसा करेंगे head, tail = lst[0], lst[1:]? यदि ओपी का अर्थ शाब्दिक उपयोग करना है तो वह सिर और पूंछ को मैन्युअल रूप से विभाजित कर सकता हैhead, tail = 1, [1, 2, 3, 5, 8, 13, 21, 34, 55]
पीना

1
(1) Op का प्रश्न था कि क्या यह एक पंक्ति में करना संभव है (इसलिए lst = ...पिछली पंक्ति में नहीं )। (२) कर head, tail = lst[0], lst[1:]कोड साइड-इफेक्ट्स (विचार head, tail = get_list()[0], get_list()[1:]) के लिए खुला छोड़ देता है , और Op के फॉर्म से अलग होता है head, tail = **some_magic applied to** [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
BobIsNotMyName 1

यह कहा जा रहा है, मैं स्वीकार करता हूं कि यह सिर / पूंछ प्राप्त करने के लिए एक खराब तरीका है। लेकिन मुझे लगा कि यह Op के विशिष्ट प्रश्न के लिए पायथन 2 के लिए सबसे अच्छा जवाब था।
BobIsNotMyName 1

1

@GarethLatty से पायथन 2 समाधान पर निर्माण, पायथन 2 में मध्यवर्ती चर के बिना एक पंक्ति के बराबर प्राप्त करने का एक तरीका है।

t=iter([1, 1, 2, 3, 5, 8, 13, 21, 34, 55]);h,t = [(h,list(t)) for h in t][0]

यदि आपको अपवाद-प्रमाण होना चाहिए (अर्थात खाली सूची का समर्थन करना), तो जोड़ें:

t=iter([]);h,t = ([(h,list(t)) for h in t]+[(None,[])])[0]

यदि आप इसे अर्धविराम के बिना करना चाहते हैं, तो उपयोग करें:

h,t = ([(h,list(t)) for t in [iter([1,2,3,4])] for h in t]+[(None,[])])[0]
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.