क्या पाइथन लैम्ब्डा अभिव्यक्ति में कई कथन होना संभव है?


112

मैं एक अजगर नौसिखिया निम्नलिखित प्राप्त करने की कोशिश कर रहा हूँ:

मेरे पास सूचियों की एक सूची है:

lst = [[567,345,234],[253,465,756, 2345],[333,777,111, 555]]

मैं चाहता हूं कि प्रत्येक सूची में से केवल दूसरी सबसे छोटी संख्या वाली एक अन्य सूची में मैप लास्ट हो। तो परिणाम होना चाहिए:

[345, 465, 333]

उदाहरण के लिए अगर मुझे सबसे छोटी संख्या में दिलचस्पी थी, तो मैं कर सकता था:

map(lambda x: min(x),lst)

काश मैं ऐसा कर पाता:

map(lambda x: sort(x)[1],lst)

लेकिन तरह श्रृंखला नहीं है। (कोई नहीं लौटाता)

न तो कुछ इस तरह की अनुमति है:

map(lambda x: sort(x); x[1],lst) #hence the multiple statement question

क्या अजगर में नक्शे के साथ ऐसा करने का एक तरीका है लेकिन एक नामित फ़ंक्शन को परिभाषित किए बिना ? (यह रूबी में गुमनाम ब्लॉकों के साथ आसान है, उदाहरण के लिए)


यकीन के लिए यह संभव होना चाहिए .. शायद एक नए संस्करण में ...
— ZEE

1
आप कथनों पर अमल नहीं कर सकते हैं, लेकिन आप लंबोदा फ़ंक्शन में फ़ंक्शन को कॉल कर सकते हैं, इसलिए unpythonic गंदे हैक lambda x: sort(x) OR x[1]काम करेगा: यहां OR एक बूल (=> झूठी) के रूप में अपने पहले तर्क (वापसी मान) का मूल्यांकन नहीं करता है, और उस स्थिति में हो सकता है अपना दूसरा तर्क देता है। लेकिन जैसा कि जवाब कहते हैं, बेहतर लंबोदर से बचें।
— अधिकतम

जवाबों:


136

आपके विशिष्ट प्रश्न से लेकर अधिक सामान्य चिंताओं तक, मैं यहां कई अलग-अलग उत्तर दे सकता हूं। तो सबसे विशिष्ट से सबसे सामान्य तक:

प्र। क्या आप एक लंबोदर में कई बयान दे सकते हैं?

A. नहीं, लेकिन आपको वास्तव में एक लैम्ब्डा का उपयोग करने की आवश्यकता नहीं है। आप बयानों को defबदले में रख सकते हैं । अर्थात:

def second_lowest(l):
    l.sort()
    return l[1]

map(second_lowest, lst)

प्र। क्या आप सूची को क्रमबद्ध करके लंबोदर से दूसरी सबसे कम वस्तु प्राप्त कर सकते हैं?

उ। हाँ। जैसा कि एलेक्स का जवाब बताता है, sorted()एक प्रकार का संस्करण है जो एक नई सूची बनाता है, छँटाई के बजाय एक जगह बनाता है, और इसे जंजीर बनाया जा सकता है। ध्यान दें कि यह संभवतः वही है जिसका आपको उपयोग करना चाहिए - मूल सूची पर दुष्प्रभाव के लिए आपके नक्शे का बुरा होना।

प्र। मुझे सूचियों के अनुक्रम में प्रत्येक सूची से दूसरी सबसे कम वस्तु कैसे प्राप्त करनी चाहिए?

A. sorted(l)[1] वास्तव में इसके लिए सबसे अच्छा तरीका नहीं है। इसमें O (N log (N)) जटिलता है, जबकि O (n) समाधान मौजूद है। यह heapq मॉड्यूल में पाया जा सकता है।

>>> import  heapq
>>> l = [5,2,6,8,3,5]
>>> heapq.nsmallest(l, 2)
[2, 3]

तो बस उपयोग करें:

map(lambda x: heapq.nsmallest(x,2)[1],  list_of_lists)

यह आमतौर पर एक सूची समझ का उपयोग करने के लिए स्पष्ट माना जाता है, जो लंबोदर से पूरी तरह से बचता है:

[heapq.nsmallest(x,2)[1] for x in list_of_lists]

3
मुझे नहीं लगता कि आप हेपैक मॉड्यूल में पाए जा रहे O (n) समाधान के बारे में सही हैं। आप जो कुछ भी कर रहे हैं, वह सूची को छाँटने में है, जो O (n log n) है और फिर सबसे छोटे तत्वों को खोज रहा है।
— avpx 20

8
प्रलेखन ( docs.python.org/2/library/heapq.html#heapq.nsmallest ) वास्तव में चेतावनी देता है कि heapq.nsmallest () का उपयोग करने से छंटनी () का उपयोग करने की तुलना में कम कुशल हो सकता है, इसलिए केवल माप ही बता सकता है कि कौन सा उपाय बता सकता है आपके मामले में सबसे तेज। heapq.nsmallest () में हालांकि O की जटिलता है (k * log (n) + n) मुझे लगता है, सूची की लंबाई के साथ n और k के साथ सबसे छोटी वस्तुओं की संख्या जिन्हें आप निकालना चाहते हैं। O (n) सूची और k गुना O (लॉग (n)) को पॉप k आइटम पॉप करने के लिए। यह ओ (एन * लॉग (एन)) से बेहतर है, खासकर छोटे कश्मीर के लिए।
— भंवर

2
@Vortexfive और निरंतर k('दूसरी सबसे कम' के रूप में) के O(k*log(n)+n)लिएO(n)
— डंकन

5
आपको तकनीकी रूप से वन-लाइनर्स के लिए लैम्बडा की आवश्यकता नहीं है, लेकिन यह निश्चित रूप से अधिक सुविधाजनक है। उम्मीद है कि बेहतर लैंबडा समर्थन बाद में जोड़ा जाएगा।
— जेम्स

1
@avpx: यह एक ढेर नहीं है। हम केवल देखे गए 2 सबसे छोटी वस्तुओं के 2-तत्व के ढेर को बनाए रखते हैं, बल्कि पूरी सूची को सुधारने और सभी तत्वों को ढेर करने के रूप में करते हैं।
— user2357112

81

एक सूची में बयानों को रखना कई बयानों का अनुकरण कर सकता है:

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

lambda x: [f1(x), f2(x), f3(x), x+1]

9
बस स्पष्ट करने के लिए, फ़ंक्शन कॉल को पायथन में बयान नहीं माना जाता है, वे अभिव्यक्ति हैं। तो यह सूची सिर्फ अभिव्यक्ति की एक सूची है, जो सभी हो सकती है None।
— यवर

मुझे लगता है कि यह काम करता है क्योंकि जब गतिशील रूप से लैम्ब्डा को दिए गए संग्रह का विश्लेषण करता है तो दुभाषिया कॉल करने योग्य हस्ताक्षर का पता लगाता है और उन्हें निष्पादित करता है ... आप के साथ परीक्षण कर सकते हैं -> लैम्ब्डा x: [प्रिंट (x), प्रिंट (x + 1), प्रिंट (x) +2)]
— ZEE

5
इससे भी बेहतर: लैम्ब्डा x: [f1 (x), f2 (x)] [- 1], यह गणना परिणाम को अंतिम अभिव्यक्ति के रूप में लौटाएगा, जैसा कि संभवतः अपेक्षित था।
— एंटोन ओवेस्निकिकोव

22

समय यात्री यहाँ। यदि आप आम तौर पर एक मेमने के भीतर कई बयान देना चाहते हैं, तो आप उस मेमने के तर्क के रूप में अन्य भेड़ के बच्चे को पास कर सकते हैं।

(lambda x, f: list((y[1] for y in f(x))))(lst, lambda x: (sorted(y) for y in x))

आपके पास वास्तव में कई स्टेटमेंट नहीं हो सकते हैं, लेकिन आप लैम्बदास को लैम्ब्डा पास करके अनुकरण कर सकते हैं।

संपादित करें: समय यात्री लौटता है! आप बूलियन अभिव्यक्तियों के व्यवहार का भी दुरुपयोग कर सकते हैं (चेन संचालन के लिए छोटे-चक्कर लगाने वाले नियमों और सच्चाई को ध्यान में रखते हुए)। टर्नेरी ऑपरेटर के उपयोग से आपको और भी अधिक शक्ति मिलती है। फिर से, आपके पास कई कथन नहीं हो सकते हैं , लेकिन आप निश्चित रूप से कई फ़ंक्शन कॉल कर सकते हैं। यह उदाहरण डेटा के एक समूह के साथ कुछ मनमाना कबाड़ करता है, लेकिन, यह दर्शाता है कि आप कुछ मज़ेदार चीजें कर सकते हैं। प्रिंट स्टेटमेंट फ़ंक्शंस के उदाहरण हैं जो लौटते हैं None(जैसा कि .sort()विधि है) लेकिन वे यह दिखाने में भी मदद करते हैं कि क्या lambdaकर रहा है।

>>> (lambda x: print(x) or x+1)(10)
10
11
>>> f = (lambda x: x[::2] if print(x) or x.sort() else print(enumerate(x[::-1]) if print(x) else filter(lambda (i, y): print((i, y)) or (i % 3 and y % 2), enumerate(x[::-1]))))
>>> from random import shuffle
>>> l = list(range(100))
>>> shuffle(l)
>>> f(l)
[84, 58, 7, 99, 17, 14, 60, 35, 12, 56, 26, 48, 55, 40, 28, 52, 31, 39, 43, 96, 64, 63, 54, 37, 79, 25, 46, 72, 10, 59, 24, 68, 23, 13, 34, 41, 94, 29, 62, 2, 50, 32, 11, 97, 98, 3, 70, 93, 1, 36, 87, 47, 20, 73, 45, 0, 65, 57, 6, 76, 16, 85, 95, 61, 4, 77, 21, 81, 82, 30, 53, 51, 42, 67, 74, 8, 15, 83, 5, 9, 78, 66, 44, 27, 19, 91, 90, 18, 49, 86, 22, 75, 71, 88, 92, 33, 89, 69, 80, 38]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
(0, 99)
(1, 98)
(2, 97)
(3, 96)
(4, 95)
(5, 94)
(6, 93)
(7, 92)
(8, 91)
(9, 90)
(10, 89)
(11, 88)
(12, 87)
(13, 86)
(14, 85)
(15, 84)
(16, 83)
(17, 82)
(18, 81)
(19, 80)
(20, 79)
(21, 78)
(22, 77)
(23, 76)
(24, 75)
(25, 74)
(26, 73)
(27, 72)
(28, 71)
(29, 70)
(30, 69)
(31, 68)
(32, 67)
(33, 66)
(34, 65)
(35, 64)
(36, 63)
(37, 62)
(38, 61)
(39, 60)
(40, 59)
(41, 58)
(42, 57)
(43, 56)
(44, 55)
(45, 54)
(46, 53)
(47, 52)
(48, 51)
(49, 50)
(50, 49)
(51, 48)
(52, 47)
(53, 46)
(54, 45)
(55, 44)
(56, 43)
(57, 42)
(58, 41)
(59, 40)
(60, 39)
(61, 38)
(62, 37)
(63, 36)
(64, 35)
(65, 34)
(66, 33)
(67, 32)
(68, 31)
(69, 30)
(70, 29)
(71, 28)
(72, 27)
(73, 26)
(74, 25)
(75, 24)
(76, 23)
(77, 22)
(78, 21)
(79, 20)
(80, 19)
(81, 18)
(82, 17)
(83, 16)
(84, 15)
(85, 14)
(86, 13)
(87, 12)
(88, 11)
(89, 10)
(90, 9)
(91, 8)
(92, 7)
(93, 6)
(94, 5)
(95, 4)
(96, 3)
(97, 2)
(98, 1)
(99, 0)
[(2, 97), (4, 95), (8, 91), (10, 89), (14, 85), (16, 83), (20, 79), (22, 77), (26, 73), (28, 71), (32, 67), (34, 65), (38, 61), (40, 59), (44, 55), (46, 53), (50, 49), (52, 47), (56, 43), (58, 41), (62, 37), (64, 35), (68, 31), (70, 29), (74, 25), (76, 23), (80, 19), (82, 17), (86, 13), (88, 11), (92, 7), (94, 5), (98, 1)]

7

सॉर्ट किए गए फ़ंक्शन का उपयोग करें , जैसे:

map(lambda x: sorted(x)[1],lst)

ah.Thanks। (क्या समारोह के लिए एक वर्णनात्मक नाम!) अभी भी भेड़ के बच्चे के भीतर कई बयान के बारे में उत्सुक। मुमकिन?
— ottodidakt

1
नहींं, "मेमने के रूपों के साथ बनाए गए कार्यों में कथन नहीं हो सकते हैं"। docs.python.org/reference/expressions.html#lambda
— एलेक्स

1
-1: सूची बोध के बजाय लंबोदर और मानचित्र? बहुत पाइथोनिक नहीं है।
— निको

@nikow [x [1] क्रमबद्ध (सूची) में x के लिए - पाइथोनिक तरीका?
— RaGa__M

@Explorer_N: सूची को क्रमबद्ध नहीं किया जाना चाहिए, लेकिन सूची के तत्व (जो सूची हैं) को वर्तमान समस्या में क्रमबद्ध किया जाना चाहिए। इसलिए बल्कि [sorted(x)[1] for x in list_of_lists]:।
— अधिकतम

6

आप वास्तव में अजगर में एक भेड़ के बच्चे की अभिव्यक्ति में कई बयान दे सकते हैं। यह पूरी तरह से तुच्छ नहीं है, लेकिन आपके उदाहरण में, निम्नलिखित काम करता है:

map(lambda x: x.sort() or x[1],lst)

आपको यह सुनिश्चित करना होगा कि प्रत्येक कथन कुछ भी वापस नहीं करता है या यदि वह इसे (.. और गलत) में लपेटता है। परिणाम वह है जो अंतिम मूल्यांकन द्वारा वापस किया जाता है।

उदाहरण:

>>> f = (lambda : (print(1) and False) or (print(2) and False) or (print(3) and False))
>>> f()
1
2
3

5

यहां से शुरू () का उपयोग कर: http://www.reddit.com/r/Python/comments/hms4z/ask_pyreddit_if_you_were_making_your_own/c1wycci

Python 3.2 (r32:88445, Mar 25 2011, 19:28:28) 
[GCC 4.5.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> lst = [[567,345,234],[253,465,756, 2345],[333,777,111, 555]]
>>> begin = lambda *args: args[-1]
>>> list(map(lambda x: begin(x.sort(), x[1]), lst))
[345, 465, 333]

4

अजगर में एक बयान में कई बयानों को संयोजित करने के लिए एक हैक करने का तरीका शॉर्ट सर्किट ऑपरेटर के रूप में "और" कीवर्ड का उपयोग करना है। फिर आप इस एकल कथन का उपयोग सीधे लंबोदर अभिव्यक्ति के हिस्से के रूप में कर सकते हैं।

यह बैश जैसे शेल भाषाओं में शॉर्ट-सर्किट ऑपरेटर के रूप में "&&" का उपयोग करने के समान है।

यह भी ध्यान दें: आप फ़ंक्शन को लपेटकर एक सही मान वापस करने के लिए हमेशा फ़ंक्शन स्टेटमेंट को ठीक कर सकते हैं।

उदाहरण:

def p2(*args):
    print(*args)
    return 1 # a true value

junky = lambda x, y: p2('hi') and p2('there') and p2(x) and p2(y)

junky("a", "b")

दूसरे विचार में, इसकी संभवतः 'या' के बजाय 'या' का उपयोग करना बेहतर है क्योंकि कई कार्य '0' पर लौटते हैं या कोई भी सफलता पर नहीं होता है। फिर आप उपरोक्त उदाहरण में आवरण समारोह से छुटकारा पा सकते हैं:

junky = lambda x, y: print('hi') or print('there') or print(x) or print(y)

junky("a", "b")

'और' संचालन भावों का मूल्यांकन तब तक करेगा जब तक कि यह पहले शून्य रिटर्न मान को प्राप्त न हो जाए। जिसके बाद यह शॉर्ट-सर्किट हुआ। 1 और 1 और 0 और 1 का मूल्यांकन करता है: 1 और 1 और 0, और 1 बूँदें

'या' संचालन तब तक भावों का मूल्यांकन करेगा जब तक कि यह पहले गैर-शून्य रिटर्न मान को प्राप्त न हो जाए। जिसके बाद यह शॉर्ट-सर्किट हुआ।

0 या 0 या 1 या 0 0 या 0 या 1 का मूल्यांकन करता है, और 0 ड्रॉप करता है


3

या यदि आप लैम्बडा से बचना चाहते हैं और सूची के बजाय एक जनरेटर है:

(सॉर्ट किया गया (कॉल) [1] lst में कॉल के लिए)


2

मुझे आप के लिए एक शानदार लेकिन भयानक हैक पेश करते हैं:

import types

def _obj():
  return lambda: None

def LET(bindings, body, env=None):
  '''Introduce local bindings.
  ex: LET(('a', 1,
           'b', 2),
          lambda o: [o.a, o.b])
  gives: [1, 2]

  Bindings down the chain can depend on
  the ones above them through a lambda.
  ex: LET(('a', 1,
           'b', lambda o: o.a + 1),
          lambda o: o.b)
  gives: 2
  '''
  if len(bindings) == 0:
    return body(env)

  env = env or _obj()
  k, v = bindings[:2]
  if isinstance(v, types.FunctionType):
    v = v(env)

  setattr(env, k, v)
  return LET(bindings[2:], body, env)

अब आप इस LETफॉर्म का उपयोग इस प्रकार कर सकते हैं :

map(lambda x: LET(('_', x.sort()),
                  lambda _: x[1]),
    lst)

जो देता है: [345, 465, 333]


मूल रूप से यहां पोस्ट किया गया: gist.github.com/divs1210/d218d4b747b08751b2a232260321cdeb
— divs1210

1

आप इसे O (n) समय में मिन या इंडेक्स का उपयोग करके सॉर्ट या हीपैक का उपयोग करने के बजाय कर सकते हैं।

पहले मूल सूची के न्यूनतम मूल्य को छोड़कर सभी चीजों की नई सूची बनाएं:

new_list = lst[:lst.index(min(lst))] + lst[lst.index(min(lst))+1:]

फिर नई सूची का न्यूनतम मूल्य लें:

second_smallest = min(new_list)

अब सभी एक ही मेमने में एक साथ:

map(lambda x: min(x[:x.index(min(x))] + x[x.index(min(x))+1:]), lst)

हाँ, यह वास्तव में बदसूरत है, लेकिन इसे एल्गोरिदम से सस्ता होना चाहिए। इस सूत्र में कुछ लोग सूची बोध देखना चाहते हैं:

[min(x[:x.index(min(x))] + x[x.index(min(x))+1:]) for x in lst]

1

यह वास्तव bindमें एक मोनाड में क्या कार्य है लिए उपयोग किया जाता है।

bindफ़ंक्शन के साथ आप एक मेमने में कई लैम्ब्डा को जोड़ सकते हैं, प्रत्येक लैम्बडा एक स्टेटमेंट का प्रतिनिधित्व कर सकता है।


1

वास्तव में एक तरीका है जिससे आप लैम्बडा में कई स्टेटमेंट्स का उपयोग कर सकते हैं। यहाँ मेरा समाधान है:

lst = [[567,345,234],[253,465,756, 2345],[333,777,111, 555]]

x = lambda l: exec("l.sort(); return l[1]")

map(x, lst)

कोड execको एक बुद्धिमान IDE द्वारा
— संरक्षित

0

हाँ। आप इसे इस तरह परिभाषित कर सकते हैं और फिर निम्नलिखित के साथ अपने कई भावों को लपेट सकते हैं:

योजना शुरू:

शुरुआत = लैम्ब्डा * x: x [-1]

आम लिस्प प्राग:

प्रोग्न = लैम्ब्डा * x: x [-1]


0

लैम्ब्डा फ़ंक्शन का उपयोग किए बिना बेहतर समाधान हैं। लेकिन अगर हम वास्तव में लैम्ब्डा फ़ंक्शन का उपयोग करना चाहते हैं, तो यहां कई कथनों से निपटने के लिए एक सामान्य समाधान है: मैप (लैम्ब्डा x: x [1] अगर (x.sort ()) x [1], lst)

आपको वास्तव में परवाह नहीं है कि कथन क्या लौटाता है।


0

हाँ यह संभव है। नीचे कोड स्निपेट आज़माएं।

x = [('human', 1), ('i', 2), ('am', 1), ('.', 1), ('love', 1), ('python', 3), ('', 1),
  ('run', 1), ('is', 2), ('robust', 1), ('hello', 1), ('spark', 2), ('to', 1), ('analysis', 2), ('on', 1), ('big', 1), ('data', 1), ('with', 1), ('analysis', 1), ('great', 1)
]

rdd_filter = rdd1_word_cnt_sum.filter(lambda x: 'python' in x or 'human' in x or 'big' in x)
rdd_filter.collect()

-1

मैं आपको एक और समाधान दूंगा, अपने लैंबडा को एक फ़ंक्शन बनाएं।

def multiple_statements(x, y):
    print('hi')
    print('there')
    print(x)
    print(y)
    return 1

junky = lambda x, y: multiple_statements(x, y)

junky('a', 'b');

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