2010-11-01 8 views
41

मैं बहुत की तरह एक वर्ग संरचना है:क्या कार्टेशियन उत्पाद करने के लिए कोई अच्छा LINQ तरीका है?

Person 
Dogs (dog 1, dog 2, etc) 
Puppies (puppy A, puppy B, etc) 

वहाँ एक व्यक्ति है। उसके पास 1. कुत्ते हैं। प्रत्येक कुत्ते में 1. एन पिल्ले होते हैं।

मैं पिल्ले के सभी संभावित संयोजनों की एक सूची चाहता हूं, प्रत्येक कुत्ते से 1 पिल्ला लेना। उदाहरण के लिए:

कुत्ता 1 पिल्ला ए, कुत्ता 2 पिल्ला एक कुत्ता 1 पिल्ला ए, कुत्ता 2 पिल्ला बी कुत्ता 1 पिल्ला बी, कुत्ता 2 पिल्ला एक कुत्ता 1 पिल्ला बी, कुत्ता 2 पिल्ला बी

हैं यह एसक्यूएल टेबल में था, मैं 'गुणा' तालिकाओं के लिए निम्नलिखित की तरह कुछ करना चाहते हैं:

select * from puppies a, puppies b where a.parent='dog1' and b.parent='dog2' 

इस थोड़े बात करने के लिए कुछ LINQ-ish रास्ता नहीं है ???

धन्यवाद इतना

उत्तर

62

अगर मैं सवाल को समझते हैं, आप पिल्लों की n सेट की कार्तीय उत्पाद चाहते हैं।

यह कार्तीय उत्पाद प्राप्त करने के लिए संकलन समय पर अगर आप जानते हैं कि कितने सेट देखते हैं आसान है:

from p1 in dog1.Puppies 
from p2 in dog2.Puppies 
from p3 in dog3.Puppies 
select new {p1, p2, p3}; 

मान लीजिए dog1 पिल्लों P11, p12 है, dog2 पिल्ला p21 है, और dog3 पिल्लों P31 है, p32। यह आपको

{p11, p21, p31}, 
{p11, p21, p32}, 
{p12, p21, p31}, 
{p12, p21, p32} 

जहां प्रत्येक पंक्ति एक अज्ञात प्रकार है। यदि आप संकलित समय पर नहीं जानते हैं कि कितने सेट हैं, तो आप इसे और अधिक काम के साथ कर सकते हैं।

http://ericlippert.com/2010/06/28/computing-a-cartesian-product-with-linq/

और इस StackOverflow सवाल: मेरे लेख इस विषय पर देखें

Generating all Possible Combinations

एक बार जब आप विधि CartesianProduct<T> है तो आप कह सकते हैं

CartesianProduct(from dog in person.Dogs select dog.Puppies) 

पाने के लिए
{p11, p21, p31}, 
{p11, p21, p32}, 
{p12, p21, p31}, 
{p12, p21, p32} 

जहां प्रत्येक पंक्ति पिल्लों का अनुक्रम है।

समझ में आओ?

+0

बिंगो! सहायता के लिए धन्यवाद। – Chris

+0

तो क्या मैं यह कहने में सही होगा कि यह पुनरावर्ती प्रोग्रामिंग का विकल्प है? –

+2

@ निक: मुझे लगता है कि यह कहना अधिक जर्मन होगा कि यह * अनिवार्य * प्रोग्रामिंग का विकल्प है। LINQ का बिंदु यह है कि आप जो चाहते हैं उसे कहते हैं - आप प्रोग्राम * घोषणात्मक * - और संकलक आंकड़े उपलब्ध रनटाइम पुस्तकालयों के आधार पर इसे कैसे करें। यदि वे पुस्तकालय रिकर्सिव प्रोग्रामिंग या पुनरावृत्त प्रोग्रामिंग का उपयोग करके अपना काम करते हैं, तो यह उनका व्यवसाय है। –

12

dogs.Join (पिल्ले,() => true,() => true, (एक, दो) => नई टपल (एक, दो));

आप नियमित रूप से शामिल हो सकते हैं, लेकिन चयनकर्ता दोनों एक ही मूल्य लौट रहे हैं, क्योंकि मैं सभी संयोजनों को वैध होना चाहता हूं। संयोजन करते समय, दोनों को एक टुपल (या अपने चयन की एक अलग डेटा संरचना) में डाल दें।

leftSide.SelectMany((l) => rightSide, (l, r) => new Tuple(l, r)); 

यह कार्टेशियन उत्पाद करना चाहिए।

+0

बहुत बहुत धन्यवाद। वाह, जटिल है। यह दिखाने के लिए जाता है कि उन्होंने लिनक की क्वेरी समझ वाक्यविन्यास का आविष्कार क्यों किया, यह निश्चित रूप से इस तरह के उदाहरणों में धाराप्रवाह से अधिक पठनीय है। – Chris

+0

@Eric Lippert कई IENumerable (उसी प्रकार की विभिन्न वस्तुओं से) को एक आईनेमेरेबल में पतन करने के लिए SelectMany का बिंदु नहीं है? प्रलेखन को देखने के बाद, मुझे क्वेरी एन सिंटैक्स के बिना LINQ में अपने एन कार्टेशियन उत्पाद का अनुवाद करने का एक अलग तरीका नहीं मिल रहा है। कार्टेशियन उत्पाद के सीमित सेट के रूप में परिभाषित नहीं किया गया है? क्या मैं एक ऑपरेटर लापता हूं? क्या क्लॉज केवल फोरैच क्लॉज के बराबर है, या क्या कोई अलग ऑपरेटर है? – McKay

+2

यह बहुत सारे प्रश्न हैं। (1) एकाधिक IENumerable को एक IENumerable में संकुचित करने के लिए SelectMany का बिंदु नहीं है? हां, बेशक यह सिर्फ इतना ही करता है। "अनुक्रम" बिंदु दृश्य से, SelectMany पिछली छोर पर प्रक्षेपण के साथ कार्टेशियन उत्पाद ऑपरेटर है। अधिक सामान्य "मोनैड" दृष्टिकोण से, SelectMany मोनैड पैटर्न पर बाइंड ऑपरेशन है। –

9

आप कुत्ते और पिल्ला के सभी संभव संयोजनों चाहते हैं, आप एक क्रॉस में शामिल होने करना होगा:

from dog in Dogs 
from puppy in Puppies 
select new 
{ 
    Dog = dog, 
    Puppy = puppy 
} 
+0

मैं वास्तव में पिल्ले के एन सेट के सभी संभावित संयोजन चाहता हूं, लेकिन मुझे सही रास्ते पर रखने के लिए धन्यवाद। – Chris