[英]What is the best way to translate this recursive python method into Java?
在另一个问题中,我得到了一个很好的答案,其中涉及为中国邮递员问题生成某些集合。
提供的答案是:
def get_pairs(s):
if not s: yield []
else:
i = min(s)
for j in s - set([i]):
for r in get_pairs(s - set([i, j])):
yield [(i, j)] + r
for x in get_pairs(set([1,2,3,4,5,6])):
print x
这将输出以下结果:
[(1, 2), (3, 4), (5, 6)]
[(1, 2), (3, 5), (4, 6)]
[(1, 2), (3, 6), (4, 5)]
[(1, 3), (2, 4), (5, 6)]
[(1, 3), (2, 5), (4, 6)]
[(1, 3), (2, 6), (4, 5)]
[(1, 4), (2, 3), (5, 6)]
[(1, 4), (2, 5), (3, 6)]
[(1, 4), (2, 6), (3, 5)]
[(1, 5), (2, 3), (4, 6)]
[(1, 5), (2, 4), (3, 6)]
[(1, 5), (2, 6), (3, 4)]
[(1, 6), (2, 3), (4, 5)]
[(1, 6), (2, 4), (3, 5)]
[(1, 6), (2, 5), (3, 4)]
这确实展示了Python的表现力,因为这几乎就是我为算法编写伪代码的方式。 我尤其喜欢收益率的使用以及将集合视为头等公民的方式。
但是,这是我的问题所在。
最好的方法是:
1.复制Java中的收益回报结构的功能吗? 相反,最好是维护一个列表并将我的部分结果附加到此列表中吗? 您将如何处理yield关键字。
2.处理成套物品? 我知道我可能会使用实现Set接口的Java集合之一,然后使用removeAll()之类的东西给我带来一些不同。 在这种情况下,您会这样做吗?
最终,我希望将这种方法简化为Java中尽可能简洁明了的方法。 我在想这种方法的Java版本的返回类型可能会返回一个int数组或类似的列表。
将此方法转换为Java时,您将如何处理上述情况?
为了将生成器函数转换为Java,您必须将其重新实现为Iterable + Iterator。 例如:
def foo(x):
for i in xrange(10):
yield x * i
...
for x in foo(5):
print(x)
变为(警告:代码未经测试):
import java.util.Iterator;
import java.util.Iterable;
class Foo implements Iterable<Integer> {
public final int x;
public Foo(int x) {
this.x = x;
}
public Iterator<Integer> iterate() {
return new Iterator<Integer> {
int i = 0;
public boolean hasNext() {
return i < 10;
}
public Integer next() {
return x * (i ++);
}
};
}
}
...
for (int x : new Foo(5)) {
System.out.println(x);
}
对于集合,我确实会使用java.util.HashSet
。
您可能想在JVM上运行它。 为什么不使用Scala?
我认为您可以在scala中将python代码转换成几乎相同的代码。 比冗长的Java东西好得多。 最后是jvm字节码,可以轻松地与您的Java应用程序融合/配合使用。
这不是您要的,但是我想尝试一下,因此这是使用LINQ的C#解决方案:
static IEnumerable<IEnumerable<int>> getPairs(IEnumerable<int> list)
{
if (!list.Any())
return new [] { new int[0] };
var first = list.First();
return from second in list.Skip(1)
from pair in getPairs(list.Skip(1).Where(rest => rest != second))
select Enumerable.Concat(new [] { first, second }, pair);
}
实际上并不返回对,而只是返回整数的有序列表,但是在此之后将其切成二很容易。 另外,很高兴看到C#可以与Python的简洁性相媲美。
测试一下:
foreach (var p in getPairs(new [] { 1, 2, 3, 4, 5, 6 }))
Console.WriteLine("[" +
String.Join(",", p.Select(i => i.ToString()).ToArray()) + "]");
并输出:
[1,2,3,4,5,6]
[1,2,3,5,4,6]
[1,2,3,6,4,5]
[1,3,2,4,5,6]
[1,3,2,5,4,6]
[1,3,2,6,4,5]
[1,4,2,3,5,6]
[1,4,2,5,3,6]
[1,4,2,6,3,5]
[1,5,2,3,4,6]
[1,5,2,4,3,6]
[1,5,2,6,3,4]
[1,6,2,3,4,5]
[1,6,2,4,3,5]
[1,6,2,5,3,4]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.