2012-02-01 25 views
5

thể trùng lặp:
Generating all Possible CombinationsN-Enumerables Trong Tuyên bố LINQ?

Tôi không chắc chắn làm thế nào để cụm từ câu hỏi; nhưng tôi đã làm việc trên một câu đố logic ngớ ngẩn mà tôi đã có thể giải quyết bằng cách sử dụng một tuyên bố LINQ. Mã có liên quan trông giống như sau:

(from myA in Enumerable.Range(1, 40) 
from myB in Enumerable.Range(1, 40) 
from myC in Enumerable.Range(1, 40) 
from myD in Enumerable.Range(1, 40) 
where myA + myB + myC + myD == 40 
    && myA <= myB 
    && myB <= myC 
    && myC <= myD 
select new[] {myA, myB, myC, myD}) 

Vì vậy, về cơ bản, tạo ra tất cả các kết hợp của A, B, C D đáp ứng các tiêu chí trong mệnh đề Where.

Những gì tôi đang cố gắng làm bây giờ là khái quát hóa điều này để tôi có thể làm điều tương tự với N giá trị thay vì chỉ bốn. Ví dụ, với 3 giá trị - mã tương đương sẽ là:

(from myA in Enumerable.Range(1, 40) 
from myB in Enumerable.Range(1, 40) 
from myC in Enumerable.Range(1, 40) 
where myA + myB + myC == 40 
    && myA <= myB 
    && myB <= myC 
select new[] {myA, myB, myC}) 

Đương nhiên, tôi không muốn thay đổi mã - Tôi muốn có một chức năng mà tôi có thể gọi và cung cấp một số nguyên và có nó trả lại đúng vật.

Tôi đã thực hiện một số nỗ lực sai lầm; nhưng tôi thực sự không thể thấy cách làm như thế. Ai đó có thể chỉ cho tôi đi đúng hướng?

+4

Eric Lippert [blogged on this] (http://blogs.msdn.com/b/ericlippert/archive/2010/06/28/computing-a-cartesian- product-with-linq.aspx) liên quan đến các sản phẩm máy tính của nhiều trình tự. Nó sẽ giúp. –

+0

@AnthonyPegram - Điều đó hoàn hảo. Chính xác những gì tôi đang tìm kiếm. Nếu bạn muốn đăng câu trả lời đó, tôi sẽ chấp nhận nó. –

+0

Nó không phải là câu trả lời * của tôi *. ;) Nếu bạn muốn cung cấp tín dụng khi tín dụng đến hạn, [thử tại đây] (http://stackoverflow.com/a/3098381/414076) –

Trả lời

0

Chưa đọc liên kết và tôi không chắc đây có phải là cách tiếp cận chính xác hay không, nhưng tại sao không tưởng tượng chúng ta đang đi một cây có chiều sâu n với mỗi nút có 40 (hoặc 20 như trong ví dụ) bọn trẻ? Nó sẽ trông như thế này, sau đó:

class Program { 
    static void Main(string[] args) { 
     Walk(3).Where(l => l.Sum() == 20 && 
      l.Skip(1).Where((num, i) => num < l[i]).Count() == 0) 
     .ToList().ForEach(l => Console.WriteLine(string.Join(" ", l))); 
     Console.ReadLine(); 
    } 

    static IEnumerable<List<int>> Walk(int depth) { 
     return depth == 0 ? 
      new[] { new List<int>()} : 
      Enumerable.Range(1,20).SelectMany(i => 
       Walk(depth - 1).Select(l => l.Concat(new[] {i}).ToList())); 
    } 
}