2

我研究并发现了很多类似的请求,但没有什么是我需要的。

这是我的问题。我正在使用 C#,并且我有一个 FileInfo[] 数组,其中包含未知数量的元素。

FileInfo[] files = new FileInfo[]
{
    new FileInfo(@"C:\a.jpg"),
    new FileInfo(@"C:\b.jpg"),
    new FileInfo(@"C:\c.jpg"),
    new FileInfo(@"C:\d.jpg"),
    new FileInfo(@"C:\e.jpg"),
    new FileInfo(@"C:\f.jpg"),
    new FileInfo(@"C:\g.jpg"),
    new FileInfo(@"C:\h.jpg"),
    new FileInfo(@"C:\i.jpg"),
}; // Using 9 elements for this example

而且我需要生成这些文件的每个可能的重新排序组合的列表,而不重复这些文件。

所以,我的一些结果会是这样的(示例不是代码格式):

a, b, c, d, e, f, g, h, i
a, b, c, d, e, f, g, i, h // i & h switched
a, b, c, d, e, f, h, g, i // last 3 elements switched

a, a, b, b, c, c, d, d, e // THIS IS NOT ACCEPTED, because elements are duplicated

以此类推,直到我想出所有可能的组合

所以结果的总数应该是数组中元素数量的阶乘。在这个例子中,有 9 个元素,所以应该有 9*8*7*6*5*4*3*2*1=362,880 种可能的组合。

我已经搞砸了这几天了,我就是不能把它包起来。任何帮助表示赞赏,尤其是代码示例!

谢谢!

4

3 回答 3

5

轻松使用 Linq:

IEnumerable<FileInfo[]> permutations =
    from a in files
    from b in files.Except(new[] { a })
    from c in files.Except(new[] { a, b })
    from d in files.Except(new[] { a, b, c })
    from e in files.Except(new[] { a, b, c, d })
    from f in files.Except(new[] { a, b, c, d, e })
    from g in files.Except(new[] { a, b, c, d, e, f })
    from h in files.Except(new[] { a, b, c, d, e, f, g })
    from i in files.Except(new[] { a, b, c, d, e, f, g, h })
    select new[] { a, b, c, d, e, f, g, h, i };

编辑:

这是一个通用解决方案,适用于任意数量的项目:

static class ExtensionMethods
{
    public static IEnumerable<IEnumerable<T>> GetPermutations<T>(this IEnumerable<T> source, int count)
    {
        IEnumerable<IEnumerable<T>> result = new[] { Enumerable.Empty<T>() }; 
        for (int i = 0; i < count; i++)
        {
            result =  
                from seq in result 
                from item in source.Except(seq)
                select seq.Concat(new[] { item }); 
        } 
        return result;
    }
}

按如下方式使用它:

IEnumerable<IEnumerable<FileInfo>> permutations = files.GetPermutations(9);

(这个解决方案的灵感来自Eric Lippert 关于笛卡尔积的文章。)


编辑2:

这是使用的变体Aggregate

static class ExtensionMethods
{
    public static IEnumerable<IEnumerable<T>> GetPermutations2<T>(this IEnumerable<T> source, int count)
    {
        IEnumerable<IEnumerable<T>> seed = new[] { Enumerable.Empty<T>() }; 
        return Enumerable.Repeat(source, count)
            .Aggregate(
                seed,
                (accumulator, sequence) =>
                    from acc in accumulator
                    from item in sequence.Except(acc)
                    select acc.Concat(new[] { item }));
    }
}
于 2010-09-29T19:40:52.407 回答
1

你真的想要集合的所有排列。

编辑:这里是你正在谈论的一个例子:http: //www.codeproject.com/KB/recipes/Premutations.aspx

于 2010-09-29T19:48:05.720 回答
1

有多种算法可用于执行此操作。下面的页面列出了 3 个不同的:

计算并列出所有排列

于 2010-09-29T19:52:32.183 回答