2010-10-13 20 views
42

निम्नलिखित सरल LINQ कोडअजगर की सूची समझ बनाम नेट LINQ

string[] words = { "hello", "wonderful", "linq", "beautiful", "world" }; 

// Get only short words 
var shortWords = 
    from word in words 
    where word.Length <= 5 
    select word; 

// Print each word out 
shortWords.Dump(); 

इस प्रकार सूची समझ का उपयोग कर अजगर में अनुवाद किया जा सकता है।

words = ["hello", "wonderful", "linq", "beautiful", "world"] 
shortWords = [x for x in words if len(x) <=5] 
print shortWords 
  • LINQ सिर्फ एक और उपाय सूची समझ लागू करने के लिए है?
  • क्या उदाहरण हो सकता है कि LINQ कर सकता है लेकिन सूची समझ नहीं कर सकती है। VB में
  • LINQ क्वेरी भाव सी # में

    • LINQ मानक क्वेरी ऑपरेटरों
    • LINQ क्वेरी भाव

    सी #:

+4

आप सी # में आलसी हैं, तो यह बजाय लिखने पर विचार: words.Where (w => w.Length <5) .Dump(); – Moberg

+0

जैसा कि [मोनैड के इस महाकाव्य स्पष्टीकरण] में बताया गया है (http://www.youtube.com/watch?v=ZhuHCtR3xq8), LINQ सावधानी से मोनैडिक होने के लिए डिज़ाइन किया गया है, इसलिए इसे सरल, सुरक्षित और प्रभावी तरीके से बनाया जा सकता है । मोनाड्स और कार्यात्मक प्रोग्रामिंग महत्व में तेजी से बढ़ रहे हैं। इसलिए मैं लोगों के सुझावों का सुझाव देता हूं कि उनके उत्तरों में। – nealmcb

+1

@nealmcb एक मोनैड एक ऐसी भाषा में केवल महत्वपूर्ण है जो साझा परिवर्तनीय स्थिति का समर्थन नहीं करता है, जैसे स्थैतिक विधियां केवल उन भाषाओं में उपयोगी होती हैं जो प्रथम श्रेणी के कार्यों का समर्थन नहीं करती हैं। यह एक प्रोग्रामिंग प्रतिमान को कुछ करने की अनुमति देने के लिए वैचारिक शुद्धता को लागू करने का एक तरीका है, यह केवल पूर्ण होने के लिए उपयुक्त नहीं है। इस प्रकार, एक मोनद कभी महत्व में वृद्धि नहीं करेगा; यह स्वयं को लगाए गए सीमा के आसपास एक क्रैच है। जेनेरिक बनाम गतिशील टाइपिंग एक और उदाहरण होगा। – alcalde

उत्तर

49

(चेतावनी: विशाल उत्तर आगे। पहली क्षैतिज रेखा तक का हिस्सा एक अच्छा टीएल बनाता है; डी अनुभाग, मुझे लगता है)

मुझे यकीन नहीं है कि मैं पाइथन गुरु के रूप में अर्हता प्राप्त करता हूं ... लेकिन मुझे पाइथन में पुनरावृत्ति पर ठोस समझ है, तो चलो कोशिश करें :)

पहला बंद: अफैक, LINQ प्रश्नों को आलसी ढंग से निष्पादित किया जाता है - यदि ऐसा है, जनरेटर अभिव्यक्ति एक करीब पायथन अवधारणा है (या तो रास्ता, सूची-, dict- और सेट समझें अवधारणात्मक रूप से केवल जेनरेटर अभिव्यक्तियों को खिलाती हैं सूची/dict/सेट कन्स्ट्रक्टर!)।

इसके अलावा, एक वैचारिक अंतर भी है: LINQ डेटा संरचनाओं से पूछताछ के रूप में नाम के रूप में है। सूची-/dict-/सेट समझें इस के संभावित अनुप्रयोग हैं (उदाहरण के लिए सूची की वस्तुओं को फ़िल्टर करना और प्रक्षेपित करना)। इसलिए वे वास्तव में कम सामान्य हैं (जैसा कि हम देखेंगे, LINQ में निर्मित कई चीजें उनमें नहीं बनाई गई हैं)। इसी प्रकार, जेनरेटर एक्सप्रेशन एक बार अग्रेषित इटरेटर को जगह बनाने के लिए एक तरीका है (मुझे इसे जेनरेटर फ़ंक्शंस के लिए लैम्ब्डा के रूप में सोचना पसंद है, केवल बदसूरत, लंबे कीवर्ड के बिना;)) और जटिल क्वेरी का वर्णन करने का कोई तरीका नहीं है । वे ओवरलैप करते हैं, हां, लेकिन वे समान नहीं हैं। यदि आप पाइथन में LINQ की सभी शक्ति चाहते हैं, तो आपको एक पूर्ण जनरेटर लिखना होगा। या अंतर्निहित कई शक्तिशाली जेनरेटर और itertools में गठबंधन करें।


अब, LINQ क्षमताओं जॉन स्कीट नामित के लिए अजगर समकक्षों:

अनुमान: (x.foo for ...)

छनन: (... if x.bar > 5)

  • में शामिल (एक्स x.foo पर y में शामिल होने के y.bar के बराबर)

सबसे नज़दीकी बात ((x_item, next(y_item for y_item in y if x_item.foo == y_item.bar)) for x_item in x) होगी, मुझे लगता है।

ध्यान दें कि यह प्रत्येक x_item के लिए पूरे वाई पर पुन: सक्रिय नहीं होगा, यह केवल पहला मैच प्राप्त करेगा।

  • समूह में शामिल (एक्स x.foo पर y y.bar ग्राम में बराबर होती है में शामिल होने)

यह कठिन है। अजगर गुमनाम प्रकार नहीं है, हालांकि वे अपने आप को ऐसा करने के लिए यदि आप __dict__ साथ खिलवाड़ कोई आपत्ति नहीं है तुच्छ हैं: तो फिर

class Anonymous(object): 
    def __init__(self, **kwargs): 
     self.__dict__ = kwargs 

, हम (Anonymous(x=x, y=y) for ...) कर सकता वस्तुओं रहे हैं कि x और y है की एक सूची प्राप्त करने के लिए संबंधित मूल्यों के साथ सदस्य। सही बात आमतौर पर परिणामों को एक अनुमोदित वर्ग के निर्माता को खिलाती है, कहें, एक्सवाई।

  • ग्रुपिंग (x.bar द्वारा समूह x.foo)

अब यह बालों हो जाता है ... वहाँ कोई निर्माण में रास्ता है, afaik। लेकिन हम यह करने के लिए ourself परिभाषित कर सकते हैं अगर हम इसे की जरूरत है:

from collections import defaultdict 

def group_by(iterable, group_func): 
    groups = defaultdict(list) 
    for item in iterable: 
     groups[group_func(item)].append(item) 
    return groups 

उदाहरण:

>>> from operator import attrgetter 
>>> group_by((x.foo for x in ...), attrgetter('bar')) 
defaultdict(<class 'list'>, {some_value_of_bar: [x.foo of all x where x.bar == some_value_of_bar], some_other_value_of_bar: [...], ...}) 

यह जो कुछ भी हम समूह द्वारा hashable, हालांकि होने की आवश्यकता है। इससे बचना संभव है, और सार्वजनिक मांग होने पर मैं एक स्टैब कर दूंगा। लेकिन अब के लिए, मैं आलसी जा रहा हूँ :)

हम भी सिर्फ मूल्यों हम के आधार पर वर्गीकृत बिना समूहों में से एक iterable लौट सकते हैं, परिणाम (बेशक हम फ़ीड कर सकते हैं किlist को पाने के लिए पर .values() फोन करके कुछ हम सूचकांक और कई बार फिर से कर सकते हैं)। लेकिन कौन जानता है कि अगर हम समूह मूल्यों की जरूरत नहीं होगी ...

  • आदेश (orderby x.foo आरोही, y.bar उतरते)

छंटाई विशेष सिंटेक्स जरूरत है?बिल्ड-इन sorted पुनरावृत्तियों के लिए भी काम करता है: sorted(x % 2 for x in range(10)) या sorted(x for x in xs, key=attrgetter('foo'))। डिफ़ॉल्ट रूप से आरोही क्रमबद्ध, कीवर्ड तर्क reverse अवरोही क्रम देता है।

अलास, कई विशेषताओं द्वारा afaik सॉर्टिंग इतना आसान नहीं है, खासकर जब आरोही और अवरोही मिश्रण। हम्म ... एक नुस्खा के लिए विषय?

  • मध्यवर्ती चर (जाने tmp = x.foo)

नहीं, संभव comprehensions या जनरेटर भाव में - वे कर रहे हैं, जैसा कि नाम का कहना है कि भाव होना चाहिए (और आमतौर पर केवल एक या दो पंक्तियां फैलती हैं)। यह, हालांकि जनरेटर समारोह में पूरी तरह से संभव है:

def doubles(iterable): 
    for x in iterable: 
     times2 = x * 2 
     yield times2 

समानता:: (c for s in ("aa","bb") for c in s)


ध्यान दें कि हालांकि LINQ वस्तुओं को साथ संबंधित

(x * 2 for x in iterable) 

मध्यवर्ती चर के साथ जनरेटर के रूप में फिर से लिखा प्रतिनिधियों, अन्य प्रश्न प्रदाताओं (जैसे LINQ से SQL) अभिव्यक्ति पेड़ों में सौदा कर सकते हैं जो क्वेरी instea का वर्णन करते हैं निष्पादन योग्य प्रतिनिधियों को प्रस्तुत करने के लिए डी। यह क्वेरी को SQL (या अन्य क्वेरी भाषाओं) में अनुवादित करने की अनुमति देता है - फिर से, मुझे नहीं पता कि पाइथन उस तरह की चीज़ का समर्थन करता है या नहीं। हालांकि यह LINQ का एक महत्वपूर्ण हिस्सा है।

अजगर निश्चित रूप से ऐसी कोई बात नहीं है। सूची अभिव्यक्ति एक (संभवतः नेस्टेड) ​​फॉर-लूप में एक सादा सूची जमा करने के लिए एक-से-एक के अनुरूप होती है, जनरेटर अभिव्यक्ति जनरेटर को एक से एक के अनुरूप होती है। parser और ast मॉड्यूल को देखते हुए यह संभव होगा सिद्धांत में उदा में एक समझ परिवर्तित करने के लिए एक पुस्तकालय लिखने के लिए एक एसक्यूएल क्वेरी। लेकिन कोई भी परवाह नहीं करता है।

+2

इनमें से कुछ को "पायथनिक" (यानि देशी/मुहावरेदार) बनाने के लिए, पाइथन के 'संग्रह। नामकरण' और 'itertools.groupby' – Ghopper21

+2

को भी देखें फ़्लैटनिंग के लिए: 'itertools.chain' – Ghopper21

19

ठीक है, आप कुछ अलग बातें के बीच अंतर करने की जरूरत है वीबी के रूप में क्वेरी एक्सप्रेशन में जितना अधिक समर्थन नहीं करता है, लेकिन यहां यह है कि समर्थक है टी:

  • अनुमान (select x.foo)
  • छनन (where x.bar > 5)
  • में शामिल (x join y on x.foo equals y.bar)
  • समूह में शामिल (x join y on x.foo equals y.bar into g)
  • समूहन (group x.foo by x.bar)
  • आदेश (orderby x.foo ascending, y.bar descending)
  • इंटरमीडिएट चर (let tmp = x.foo)
  • सपाट (from x in y from z in x)

मैं कैसे उन में से कई सीधे पायथन के सूची comprehensions में समर्थित हैं पता नहीं है।

ध्यान दें कि प्रतिनिधियों के साथ हालांकि LINQ वस्तुओं के लिए सौदों, अन्य क्वेरी प्रदाता (उदा LINQ एसक्यूएल करने के लिए) अभिव्यक्ति पेड़ जो सिर्फ निष्पादन योग्य प्रतिनिधियों पेश करने के बजाय क्वेरी का वर्णन में सौदा कर सकते हैं। यह क्वेरी को SQL (या अन्य क्वेरी भाषाओं) में अनुवादित करने की अनुमति देता है - फिर से, मुझे नहीं पता कि पाइथन उस तरह की चीज़ का समर्थन करता है या नहीं। हालांकि यह LINQ का एक महत्वपूर्ण हिस्सा है।

+1

"आप जो कुछ भी कर सकते हैं, मैं बेहतर कर सकता हूं ..." pynq (https://github.com/heynemann/pynq/wiki) देखें। नारंगी संतरे की तुलना क्यों नहीं? वैसे भी, सूची की समझ LINQ से तुलनीय नहीं है क्योंकि वे एक पूरी तरह से अलग उद्देश्य प्रदान करते हैं। जहां LINQ प्रदर्शन पर अभिव्यक्ति पर जोर देती है, सूची समझ अभिव्यक्ति पर प्रदर्शन पर जोर देती है। वे एक इक्वेटर (पूर्व सूची) के निर्माता में जेनरेटर फ़ंक्शन पास करने के अलावा, IqualsComparator में गुजरने के माध्यम से सी # में एक .quals() विधि को ओवरराइड करने के समान काम करते हैं। मैं कोई गुरु नहीं हूं लेकिन यह अजगर में बहुत ही बुनियादी चीजें है। –

+1

@EvanPlaice सूची समझ जेनरेटर नहीं हैं, अंतर ब्रैकेट बनाम ब्रांड्स का उपयोग कर रहा है http://stackoverflow.com/questions/47789/generator-expressions-vs-list-comprehension, जबकि .Net Linq हमेशा स्मृति में है और कर सकते हैं उपज कीवर्ड (जेनरेटर के समान, लेकिन एकल उपयोग प्रतिबंध के बिना) उत्पन्न हो जाएं –

2

मैं कोई पायथन गुरु नहीं हूं, लेकिन मैं कहूंगा कि पाइथन वास्तव में उन सभी का समर्थन करता है क्योंकि आप सूची की समझ घोंसला कर सकते हैं और सभी लैम्ब्डा अभिव्यक्तियों को शामिल कर सकते हैं। (सूची समझने में मुश्किल होती है अगर वे बहुत जटिल हो जाते हैं, हालांकि ...), लेकिन इसमें सभी को पूरा करने के लिए कोई "विशिष्ट वाक्यविन्यास" शामिल नहीं है।

से अधिकांश कार्यक्षमता का उपयोग कर reproduced किया जा सकता है: - सूची comprehensions या जनरेटर - लैम्ब्डा-कार्य या itertools मॉड्यूल

उदाहरण के लिए से builtin कार्य (जैसे filter() या map()) या काम करता है,

  • अनुमान: आप के व्यवहार की नकल करना चाहते हैं टी टोपी एक सूची-समझ का बायां हिस्सा होगा ... जो एकल मूल्य हो सकता है लेकिन tuples भी हो सकता है। पूर्व: [ (k,v) for k,v in my_dict.items() if k.startswith("abc"]। आप map()
  • फ़िल्टरिंग फ़िल्टर कर सकते हैं: if के बाद, दाईं ओर अभिव्यक्ति होगी। तुम भी उपयोग कर सकते हैं filter()
  • आदेश: सिर्फ builtin sorted()
  • समूहन या समुच्चय का उपयोग करें: का उपयोग builtin min(), max() या itertools.groupby()

के बारे में मिलती है या flattening, मुझे लगता है कि आपको "हाथ से ऐसा करना होगा" ...

(Python Quick Reference तक पहुंचने के लिए हमेशा अच्छा है)

15

asq पायथन पैकेज का उपयोग करके आप आसानी से पाइथन में अधिकतर चीजें कर सकते हैं जो आप LINQ-for-objects का उपयोग कर सी # में कर सकते हैं। ASQ का उपयोग करना, अपने अजगर उदाहरण बन जाता है:

from asq.initiators import query 
words = ["hello", "wonderful", "linq", "beautiful", "world"] 
shortWords = query(words).where(lambda x: len(x) <= 5) 
+0

लिंक टूटा हुआ प्रयास करें: https://pypi.python.org/pypi/asq/1.0 – Anytoe

संबंधित मुद्दे