你能用 C# 编写一个同样优雅的排列函数吗?

2024-06-19

我非常喜欢这个 6 行解决方案,并尝试在 C# 中复制它。基本上,它会排列数组的元素:

def permute(xs, pre=[]):
  if len(xs) == 0:
     yield pre
  for i, x in enumerate(xs):
     for y in permute(xs[:i] + xs[i+1:], pre + [x]):
        yield y

好吧,这可能不是我的写法,但是:

static IEnumerable<T[]> Permute<T>(this T[] xs, params T[] pre) {
    if (xs.Length == 0) yield return pre;
    for (int i = 0; i < xs.Length; i++) {
        foreach (T[] y in Permute(xs.Take(i).Union(xs.Skip(i+1)).ToArray(), pre.Union(new[] { xs[i] }).ToArray())) {
            yield return y;
        }
    }
}

回复您的评论;我不是entirely问题清楚;如果你的意思是“为什么这有用?” - 除其他事项外,还有一系列暴力场景,您需要尝试不同的排列 - 例如,对于像旅行销售人员这样的小订购问题(不足以保证更复杂的解决方案),您可能想检查是否最好去 {base,A,B,C,base}, {base,A,C,B,base},{base,B,A,C,base} 等。

如果您的意思是“我将如何使用此方法?” - 未经测试,但类似:

int[] values = {1,2,3};
foreach(int[] perm in values.Permute()) {
   WriteArray(perm);
}

void WriteArray<T>(T[] values) {
    StringBuilder sb = new StringBuilder();
    foreach(T value in values) {
        sb.Append(value).Append(", ");
    }
    Console.WriteLine(sb);
}

如果你的意思是“它是如何工作的?” - 迭代器块(yield return)本身就是一个复杂的主题 - Jon 有一个免费章节 (6)在他的书中 http://www.manning.com/skeet/, 尽管。代码的其余部分非常像你原来的问题 - 只是使用 LINQ 提供道德等价物+(对于数组)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

你能用 C# 编写一个同样优雅的排列函数吗? 的相关文章

随机推荐