LINQ

2010-04-29 24 views
32

के साथ संख्या अनुक्रम उत्पन्न करें मैं LINQ कथन लिखने का प्रयास करता हूं जो मुझे संख्याओं के सभी संभावित संयोजन देता है (मुझे इसे एक परीक्षण के लिए चाहिए और मैं इस article of Eric Lippert से प्रेरित था)। विधि के प्रोटोटाइप मैं फोन लगता है:LINQ

IEnumerable<Collection<int>> AllSequences(int start, int end, int size); 

नियम हैं:

  • सभी लौटे संग्रह
  • के बीच हर संख्या में वृद्धि करने की है एक संग्रह के भीतर size
  • संख्या मूल्यों की लंबाई है start और end का उपयोग किया जाना चाहिए

तो बुला AllSequences(1, 5, 3) 10 संग्रह में परिणाम चाहिए, आकार 3 में से प्रत्येक:

1 2 3 
1 2 4 
1 2 5 
1 3 4 
1 3 5 
1 4 5 
2 3 4 
2 3 5 
2 4 5 
3 4 5 

अब, किसी भी तरह मैं वास्तव में एक शुद्ध LINQ समाधान देखना चाहते हैं। मैं अपने आप पर एक गैर LINQ समाधान लिखने में सक्षम हूं, इसलिए LINQ के बिना समाधान में कोई प्रयास न करें।
मेरे कोशिश करता अब तक एक बिंदु जहां मैं अपने विधि का एक पुनरावर्ती कॉल के परिणाम के साथ एक नंबर शामिल होने की आवश्यकता पर समाप्त हो गया - कुछ की तरह:

return from i in Enumerable.Range(start, end - size + 1) 
     select BuildCollection(i, AllSequences(i, end, size -1)); 

लेकिन मैं इसे प्रबंधन नहीं कर सकते एक पर BuildCollection() लागू करने के लिए LINQ आधार - या यहां तक ​​कि इस विधि कॉल को छोड़ दें। क्या आप यहां मेरी मदद कर सकते हैं?

+0

@Noldorin, @Fede: महान जवाब के लिए धन्यवाद - मैं निश्चित रूप से 'Enumerable' के तरीकों को करीब से देख ले जाना है (' दोहराएँ की तरह() 'या' Concat() ') – tanascius

उत्तर

32

सोचो मुझे यह मिल गया है।

IEnumerable<List<int>> AllSequences(int start, int end, int size) 
{ 
    if (size == 0) 
     return Enumerable.Repeat<List<int>>(new List<int>(), 1); 

    return from i in Enumerable.Range(start, end - size - start + 2) 
      from seq in AllSequences(i + 1, end, size - 1) 
      select new List<int>{i}.Concat(seq).ToList(); 
} 
+0

'अगर (आकार == 0) नया int वापस लौटें [] {} .सूची()'? – Spook

13

मुझे लगता है कि कुछ ऐसा करना चाहिए, मुझे लगता है।

public static IEnumerable<IEnumerable<int>> AllSequences(int start, int end, 
    int size) 
{ 
    return size <= 0 ? new[] { new int[0] } : 
      from i in Enumerable.Range(start, end - size - start + 2) 
      from seq in AllSequences(i + 1, end, size - 1) 
      select Enumerable.Concat(new[] { i }, seq); 
} 

कुंजी समाधान के लिए जो नेस्टेड enumerables से निपटने के लिए काफी उपयोगी है compound from clause है।

ध्यान दें कि मैंने विधि हस्ताक्षर को IEnumerable<IEnumerable<int>> में थोड़ा बदल दिया है, क्योंकि यह (शुद्ध) LINQ का उपयोग करते समय अधिक सुविधाजनक है। यदि आप चाहें तो अंत में आप आसानी से IEnumerable<ICollection<int>> पर आसानी से इसे परिवर्तित कर सकते हैं।

मुझे बताएं कि कोड को किसी स्पष्टीकरण की आवश्यकता है, लेकिन मुझे उम्मीद है कि LINQ वाक्यविन्यास इसे उचित रूप से स्पष्ट करता है।

संपादित करें 1: फिक्स्ड बग और बेहतर समन्वय।

संपादित करें 2: क्योंकि मैं ऊब रहा हूँ और बेहतर कुछ भी नहीं करना (कोई, नहीं वास्तव में) है, मैंने सोचा कि मैं एक विस्तार विधि है कि तत्वों की एक दी गई सूची के संयोजन की गणना लिखना चाहते हैं, इस्तेमाल कर रही है AllSequences विधि का।

public static IEnumerable<IEnumerable<T>> Combinations<T>(this IList<T> source, 
    int num) 
{ 
    return AllSequences(0, source.Count - 1, num).Select(
     seq => seq.Select(i => source[i])); 
} 

शायद कंप्यूटिंग संयोजनों का सबसे प्रभावी तरीका नहीं है, लेकिन निश्चित रूप से सुंदर कॉम्पैक्ट कोड!

+3

आपने मेरी गर्जन चुरा ली! मैं बस यह काम कर रहा था = डी +1 – Tejs

+1

मैंने अभी इसे चलाया और यह एक स्टैक ओवरफ्लो का कारण बनता है :-(, हो सकता है कि आकार> 0 के साथ, दूसरे से पहले? –

+1

इसे सभी सेवर्स में सेक से होना चाहिए (i +1, अंत, आकार -1) ' इसके अलावा, अच्छा! मैंने अभी भी एक लिखा है, लेकिन आपका बहुत अधिक संक्षिप्त है। +1 – tzaman

41
Enumerable.Range(1, 12) 
      .Select(x => (x - 1) + 1); 
+2

ने सवाल का जवाब नहीं दिया, लेकिन मेरे लिए उपयोगी था, इसलिए +1 – Kell

+1

यह क्या करता है? 'चयन' अनावश्यक नहीं है? –

+0

@MateenUlhaq हां, यह अनावश्यक प्रतीत होता है। –

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

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