下面的程序可以根据需要运行,但如何减少if语句的数量。有人告诉我,如果你的函数包含2个或更多if语句,那么你做错了。有什么建议?我尝试过使用switch语句,但由于案例不能是布尔值,因此无效。
for(int i = 1; i < 100; i++)
{
if(i % 10 == 3)
{
System.out.println("Fizz" + "(" + i + ") 3%10");
}
if(i / 10 == 3)
{
System.out.println("Fizz" + "(" + i + ") 3/10");
}
if(i % 10 == 5)
{
System.out.println("Buzz" + "(" + i + ") 5%10");
}
if(i / 10 == 5)
{
System.out.println("Fizz" + "(" + i + ") 5/10");
}
if(i / 10 == 7)
{
System.out.println("Fizz" + "(" + i + ") 7/10");
}
if(i%10 == 7)
{
System.out.println("Woof" + "(" + i + ") 7%10");
}
if(i % 3 == 0)
{
System.out.println("Fizz" + "(" + i + ") 3%==0");
}
if(i % 5 == 0)
{
System.out.println("Buzz" + "(" + i + ")5%==0");
}
if(i % 7 == 0)
{
System.out.println("Woof" + "(" + i + ")7%==0");
}
if( (i % 7 !=0 ) && (i % 3 !=0 ) && (i % 5 !=0 )
&& (i % 10 !=3) && (i % 10 !=5 ) && (i%10 !=7 ) )
System.out.println(i);
}
答案 0 :(得分:49)
如何为案例创建方法:
public void printIfMod(int value, int mod){
if (value % 10 == mod)
System.out.println(...);
}
public void printIfDiv(int value, int div){
if (value / 10 == div)
System.out.println(...);
}
然后,您可以使用两种方法调用一组if
而不是一堆 public void printIf(int value, int div){
printIfMod(value, div);
printIfDiv(value, div);
}
for(int i = 1; i < 100; i++) {
printIf(i, 3);
printIf(i, 5);
....
}
。您甚至可以创建一个调用上述两种方法的方法。
ifs
在上面的代码中,{{1}}的数量对我来说不是重复代码的数量。
答案 1 :(得分:26)
使用两个switch语句
稍有改进switch(i / 10){
case 3: // do something
break;
case 5: // do something else
break;
case 7: // do something else
break;
}
switch(i % 10){
case 3: // do something
break;
case 5: // do something else
break;
case 7: // do something else
break;
}
不幸的是,每个除数你需要一个switch语句。
或者,您可以接受OOP并提出这样的抽象:
public abstract class Processor {
private final int divisor;
private final int result;
private final boolean useDiv; // if true, use /, else use %
public Processor(int divisor, int result, boolean useDiv) {
this.divisor = divisor;
this.result = result;
this.useDiv = useDiv;
}
public final void process(int i){
if (
(useDiv && i / divisor == result)
|| (!useDiv && i % divisor == result)
){
doProcess(i);
}
}
protected abstract void doProcess(int i);
}
样本用法:
public static void main(String[] args) {
List<Processor> processors = new ArrayList<>();
processors.add(new Processor(10, 3, false) {
@Override
protected void doProcess(int i) {
System.out.println("Fizz" + "(" + i + ") 3%10");
}
});
// add more processors here
for(int i = 1; i < 100; i++){
for (Processor processor : processors) {
processor.process(i);
}
}
}
答案 2 :(得分:12)
一般来说,拥有大量if
语句的代码看起来很可疑。可疑并不一定意味着错误。如果问题陈述有不相同的条件要检查(即你不能对它们进行分组),那么你必须像你一样独立完成它们。
在你的情况下,你必须检查可分性而不能推断另一个(即如果x可以被7整除,它并不意味着它也可以被5整除,等等......)。你正在使用的所有数字都是故意选择的素数,所以这就是你进入这个数字的原因。
例如,如果他们说过,请检查2,3和6的可分性。然后你可以先检查6,因为那时你也可以暗示2和3的可分性。反之亦然,检查2和3并且暗示它也可被6整除。如果所有数字都是素数,那么你就不能暗示。所以你的代码必须单独检查所有内容。
一个积极的副作用是它使您的意图易于在您的代码中阅读(因为它都是明确的)。
我的两分钱......
答案 3 :(得分:8)
Enums非常适合这里。它们允许您将功能封装在一个位置,而不是将其传播到整个流控制中。
public class Test {
public enum FizzBuzz {
Fizz {
@Override
String doIt(int n) {
return (n % 10) == 3 ? "3%10"
: (n / 10) == 3 ? "3/10"
: (n / 10) == 5 ? "5/10"
: (n / 10) == 7 ? "7/10"
: (n % 3) == 0 ? "3%==0"
: null;
}
},
Buzz {
@Override
String doIt(int n) {
return (n % 10) == 5 ? "5%10"
: (n % 5) == 0 ? "5%==0"
: (n / 10) == 3 ? "3/10"
: (n / 10) == 5 ? "5/10"
: (n / 10) == 7 ? "7/10"
: null;
}
},
Woof {
@Override
String doIt(int n) {
return (n % 10) == 7 ? "7%10"
: (n % 7) == 0 ? "7%==0"
: null;
}
};
// Returns a String if this one is appropriate for this n.
abstract String doIt(int n);
}
public void test() {
// Duplicates the posters output.
for (int i = 1; i < 100; i++) {
boolean doneIt = false;
for (FizzBuzz fb : FizzBuzz.values()) {
String s = fb.doIt(i);
if (s != null) {
System.out.println(fb + "(" + i + ") " + s);
doneIt = true;
}
}
if (!doneIt) {
System.out.println(i);
}
}
// Implements the game.
for (int i = 1; i < 100; i++) {
boolean doneIt = false;
for (FizzBuzz fb : FizzBuzz.values()) {
String s = fb.doIt(i);
if (s != null) {
if ( doneIt ) {
System.out.print("-");
}
System.out.print(fb);
doneIt = true;
}
}
if (!doneIt) {
System.out.print(i);
}
System.out.println();
}
}
public static void main(String args[]) {
try {
new Test().test();
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
}
答案 4 :(得分:7)
我已经开始写一个涉及代码的答案,但是很多人都打败了我。我要说的一件事还没有提到,你所指的这个特定的代码指标叫做cyclomatic complexity,并不是一个可怕的坏事。
简而言之,它指的是一个方法在执行时可以采用的不同路径的数量,虽然它在您发布的代码剪切中非常高,并且有很多很好的提示/解决方案来减少它建议,我个人认为,即使在它的当前形式,代码是非常可读 - 这是一个奖金。它可以减少相当数量并且仍然可读,但我的观点是,像这样的指标并不是一切,有时它可以更简单地拥有大量if
语句,因为它更具可读性 - 并且可读性降低了犯错的可能性,并使调试更容易
哦,我会替换最后一节:
if( (i % 7 !=0 ) && (i % 3 !=0 ) && (i % 5 !=0 )
&& (i % 10 !=3) && (i % 10 !=5 ) && (i%10 !=7 ) )
System.out.println(i);
通过在调用任何替换语句时使用诸如replaced = true
之类的布尔标志,上述语句将折叠为:
if (!replaced)
System.out.println(i);
答案 5 :(得分:7)
我认为,你问的是错误的问题。我认为你应该问的问题是:“我怎样才能重写这段代码,以便人类更容易理解?”
信条“消除if语句”是实现这一目标的一般想法,但它在很大程度上取决于上下文。
可悲的事实是,许多答案以“使其更简单”为幌子来混淆这种非常简单的算法。永远不要引入一个对象来消除一些if语句。在我的工作中,大多数代码由比原始作者更少理解体系结构,数学和代码的人维护,因此引入额外的结构和复杂性以将代码从50个物理行减少到30个物理行,但使其成为4时间更难理解不是胜利。
答案 6 :(得分:5)
您的代码是重复的。使用循环重构它:
for (int i = 1; i < 100; i++) {
boolean found = false; // used to avoid the lengthy test for "nothing found"
for (int j = 3; j <= 7; j += 2) { // loop 3, 5, 7
if (i % 10 == j) {
System.out.println("Fizz" + "(" + i + ") "+j+"%10");
found = true;
}
if (i / 10 == j) {
System.out.println("Fizz" + "(" + i + ") "+j+"/10");
found = true;
}
if (i % j == 0) {
System.out.println("Fizz" + "(" + i + ") "+j+"%==0");
found = true;
}
}
if (!found) {
System.out.println(i);
}
}
答案 7 :(得分:1)
您可以创建多个开关:
switch (i/10) {
case 3:
System.out.println("Fizz" + "(" + i + ") 3/10");
break;
case 5:
System.out.println("Fizz" + "(" + i + ") 5/10");
break;
case 7:
System.out.println("Fizz" + "(" + i + ") 7/10");
break;
default:
break;
}
switch (i%10) {
case 3:
System.out.println("Fizz" + "(" + i + ") 3%10");
break;
case 5:
System.out.println("Buzz" + "(" + i + ") 5%10");
break;
case 7:
System.out.println("Woof" + "(" + i + ") 7%10");
break;
default:
break;
}
另一种情况仍然需要使用if语句
Oracle在Java 7中添加了使用String
的switch语句。也许boolean switch语句将在以后出现。
答案 8 :(得分:0)
public class Test
{
public static void main(String[] args)
{
final int THREE = 3;
final int FIVE = 5;
final int SEVEN=7;
final int ZERO = 0;
for (int i = 1; i < 100; i++)
{
modOperation("Fizz", i, THREE);
divideOperation("Fizz", i, THREE);
modOperation("Fizz", i, FIVE);
divideOperation("Buzz", i, FIVE);
modOperation("Woof", i, SEVEN);
divideOperation("Fizz", i, SEVEN);
modOperation("Fizz", i, ZERO);
divideOperation("Fizz", i, ZERO);
}
}
private static void divideOperation(String sound, int i, int j)
{
if (i / 10 == j) // you can add/expand one more parameter for 10 and later on 3 in this example.
{
System.out.println(sound + "(" + i + ") "+j+"/10");
}
}
private static void modOperation(String sound, int i, int j)
{
if (i % 10 == j)
{
System.out.println(sound + "(" + i + ") "+j+"%10");
}
}
}
所以现在你的if