2011-09-08 93 views
1

定列表{1,2,3,4,5}从可枚举<int>

我要生成在C#中这些数字的所有可能的序列生成所有可能的序列。

1,2,3,4,5 1,2,3,5,4 等

这将是很好的,如果它是懒惰的评价,但它不是必需的。

应该返回

IEnumerable<IEnumerable<int>> 

我的目的是包装成一个自定义的LINQ操作符(“重排列”或东西)这一点。但是任何好的算法都是一个好的开始。

谢谢。

回答

5

尝试这样的事:

public static IEnumerable<List<T>> GetPermutations<T>(IEnumerable<T> items) 
    { 
     if (!items.Any()) 
      yield return new List<T>(); 
     foreach (var i in items) 
     { 
      var copy = new List<T>(items); 
      copy.Remove(i); 
      foreach(var rest in GetPermutations(copy)) 
      { 
       rest.Insert(0, i); 
       yield return rest; 
      } 
     } 
    } 

    public static IEnumerable<IEnumerable<T>> GetEnumPermutations<T>(IEnumerable<T> items) 
    { 
     return GetPermutations(items); 
    } 
当然

可以更改名单的实现在那里,但internaly我会坚持一些集合,因为删除更容易处理(。哪里是可能的,但并不像可读或高性能)

+0

这将是个好主意,检查项目是否有1或0项内 –

+0

是的 - 抱歉(我有这个,但决定缩短... ARGH) - 改回来,非常感谢Piotr – Carsten

+0

它当然有效。我正在盯着它。我不知道发生了什么事。我可以看到它递归地进行递减,直到它到达空列表为止。然后它使用调用堆栈中的“i”变量组成一个序列。该算法不会“捕捉”到我脑中的位置(例如,在返回序列中如何避免重复值“i”)。这是一些已知的算法,你只是纯粹的天才,或者除了我以外,这种方法是最明显的吗? – Tormod

0
List<int> li = new List<int> { 1, 2, 3, 4, 5 }; 
    var ff = from a in li 
      join b in li on 1 equals 1 
      join c in li on 1 equals 1 
      join d in li on 1 equals 1 
      join e in li on 1 equals 1 
      where 
      a != b && b != c && c != d && d != e && 
      a != c && b != d && c != e && 
      a != d && b != e && 
      a != e 
      select new { a, b, c, d, e }; 
+2

以及如果没有5列表中的元素?这与自己列举所有的排列差不多;) - 更好地更改或删除它。我不会给新会员一个downvote的基础上,但其他人可能会做 – Carsten