kof*_*cii 60 java coding-style
我有这个丑陋的代码:
if ( v > 10 ) size = 6;
if ( v > 22 ) size = 5;
if ( v > 51 ) size = 4;
if ( v > 68 ) size = 3;
if ( v > 117 ) size = 2;
if ( v > 145 ) size = 1;
return size;
Run Code Online (Sandbox Code Playgroud)
如何摆脱多个if语句?
mfl*_*yan 160
这种方法怎么样:
int getSize(int v) {
int[] thresholds = {145, 117, 68, 51, 22, 10};
for (int i = 0; i < thresholds.length; i++) {
if (v > thresholds[i]) return i+1;
}
return 1;
}
Run Code Online (Sandbox Code Playgroud)
功能:(在Scala中演示)
def getSize(v: Int): Int = {
val thresholds = Vector(145, 117, 68, 51, 22, 10)
thresholds.zipWithIndex.find(v > _._1).map(_._2).getOrElse(0) + 1
}
Run Code Online (Sandbox Code Playgroud)
bar*_*jak 88
使用NavigableMapAPI:
NavigableMap<Integer, Integer> s = new TreeMap<Integer, Integer>();
s.put(10, 6);
s.put(22, 5);
s.put(51, 4);
s.put(68, 3);
s.put(117, 2);
s.put(145, 1);
return s.lowerEntry(v).getValue();
Run Code Online (Sandbox Code Playgroud)
Ale*_*ing 81
OPs解决方案最明显的问题是分支,所以我建议进行多项式回归.这将在表单上产生一个很好的无分支表达式
size = round(k_0 + k_1 * v + k_2 * v^2 + ...)
Run Code Online (Sandbox Code Playgroud)
你当然不会得到一个确切的结果,但如果你能容忍一些偏差,那么这是一个非常高效的选择.由于对于v<10无法用多项式建模的值的原始函数的"保留未修改"行为,我冒昧地假设该区域的零阶保持插值.
对于具有以下系数的45度多项式,
-9.1504e-91 1.1986e-87 -5.8366e-85 1.1130e-82 -2.8724e-81 3.3401e-78 -3.3185e-75 9.4624e-73 -1.1591e-70 4.1474e-69 3.7433e-67 2.2460e-65 -6.2386e-62 2.9843e-59 -7.7533e-57 7.7714e-55 1.1791e-52 -2.2370e-50 -4.7642e-48 3.3892e-46 3.8656e-43 -6.0030e-41 9.4243e-41 -1.9050e-36 8.3042e-34 -6.2687e-32 -1.6659e-29 3.0013e-27 1.5633e-25 -8.7156e-23 6.3913e-21 1.0435e-18 -3.0354e-16 3.8195e-14 -3.1282e-12 1.8382e-10 -8.0482e-09 2.6660e-07 -6.6944e-06 1.2605e-04 -1.7321e-03 1.6538e-02 -1.0173e-01 8.3042e-34 -6.2687e-32 -1.6659e-29 3.0013e-27 1.5633e-25 -8.7156e-23 6.3913e-21 1.0435e-18 -3.0354e-16 3.8195e-14 -3.1282e-12 1.8382e-10 -8.0482e-09 2.6660e-07 -6.6944e-06 1.2605e-04 -1.7321e-03 1.6538e-02 -1.0173e-01 3.6100e-01 -6.2117e-01 6.3657e+00
Run Code Online (Sandbox Code Playgroud)
,你得到一个漂亮的曲线:

正如您所看到的,在0到200*的整个范围内,您只能获得1.73的1-norm误差!
*结果v?[0,200]可能会有所不同.
Jig*_*shi 75
if ( v > 145 ) size = 1;
else if ( v > 117 ) size = 2;
else if ( v > 68 ) size = 3;
else if ( v > 51 ) size = 4;
else if ( v > 22 ) size = 5;
else if ( v > 10 ) size = 6;
return size;
Run Code Online (Sandbox Code Playgroud)
这对你的情况更好.
您可以选择尽可能选择Switch Case
Update:
如果你已经分析了'v'的值,那么在大多数情况下,你通常会在较低的范围内(<10),而不是你可以添加它.
if(v < 10) size = SOME_DEFAULT_VALUE;
else if ( v > 145 ) size = 1;
else if ( v > 117 ) size = 2;
else if ( v > 68 ) size = 3;
else if ( v > 51 ) size = 4;
else if ( v > 22 ) size = 5;
else if ( v > 10 ) size = 6;
Run Code Online (Sandbox Code Playgroud)
further :
您还可以根据您的分析更改条件序列.如果您知道大多数值小于10,然后在第二位置大多数值介于68-117之间,则可以相应地更改条件序列.
编辑:
if(v < 10) return SOME_DEFAULT_VALUE;
else if ( v > 145 ) return 1;
else if ( v > 117 ) return 2;
else if ( v > 68 ) return 3;
else if ( v > 51 ) return 4;
else if ( v > 22 ) return 5;
else if ( v > 10 ) return 6;
Run Code Online (Sandbox Code Playgroud)
dhb*_*lah 51
return v > 145 ? 1
: v > 117 ? 2
: v > 68 ? 3
: v > 51 ? 4
: v > 22 ? 5
: v > 10 ? 6
: "put inital size value here";
Run Code Online (Sandbox Code Playgroud)
Jim*_*ans 23
原始代码对我来说似乎很好,但是如果你不介意多次返回,你可能更喜欢更表格的方法:
if ( v > 145 ) return 1;
if ( v > 117 ) return 2;
if ( v > 68 ) return 3;
if ( v > 51 ) return 4;
if ( v > 22 ) return 5;
if ( v > 10 ) return 6;
return ...; // The <= 10 case isn't handled in the original code snippet.
Run Code Online (Sandbox Code Playgroud)
请参阅org.life.java的答案中的多次返回或不讨论.
cbm*_*eks 17
这里有很多答案和建议,但老实说,我认为它们中的任何一个都比原始方法"更漂亮"或"更优雅".
如果你有几十次或几百次的迭代检查,那么我可以很容易地看到一些for循环但老实说,对于你的少数比较,坚持使用if并继续前进.这不是那么难看.
mha*_*ler 14
return (v-173) / -27;
Run Code Online (Sandbox Code Playgroud)
st0*_*0le 12
这是我的镜头......
更新:已修复.先前的解决方案给出了精确值的错误答案(10,22,51 ...).如果val <10,则默认值为6
static int Foo(int val)
{
//6, 5, 4, 3, 2 ,1
int[] v = new int[]{10,22,51,68,117,145};
int pos = Arrays.binarySearch(v, val-1);
if ( pos < 0) pos = ~pos;
if ( pos > 0) pos --;
return 6-pos;
}
Run Code Online (Sandbox Code Playgroud)
Eri*_*ikE 11
我还有一个版本供您使用.我真的不认为它是最好的,因为当我100%确定这个函数永远不会是一个性能损失时,它会增加"性能"名称的不必要的复杂性(除非有人在一个紧凑的循环中计算大小一百万次...).
但我提出它只是因为我认为执行硬编码二进制搜索有点有趣.它看起来不是二元-y因为没有足够的元素去深入,但它确实具有在原始帖子中不超过3次测试而不是6次返回结果的优点.返回语句也按大小排序,这有助于理解和/或修改.
if (v > 68) {
if (v > 145) {
return 1
} else if (v > 117) {
return 2;
} else {
return 3;
}
} else {
if (v > 51) {
return 4;
} else if (v > 22) {
return 5;
} else {
return 6;
}
}
Run Code Online (Sandbox Code Playgroud)
7 - (x>10 + x>22 + x>51 + x>68 + x>117 + x>145)
Run Code Online (Sandbox Code Playgroud)
其中7是默认值(x <= 10).
编辑:最初我没有意识到这个问题是关于Java的.此表达式在Java中无效,但在C/C++中有效.我会留下答案,因为有些用户觉得它很有帮助.
这是一个面向对象的解决方案,这个类被称为Mapper<S,T>映射来自任何类型的值,这些类型实现了与任何目标类型相当的.
句法:
Mapper<String, Integer> mapper = Mapper.from("a","b","c").to(1,2,3);
// Map a single value
System.out.println(mapper.map("beef")); // 2
// Map a Collection of values
System.out.println(mapper.mapAll(
Arrays.asList("apples","beef","lobster"))); // [1, 2, 3]
Run Code Online (Sandbox Code Playgroud)
码:
public class Mapper<S extends Comparable<S>, T> {
private final S[] source;
private final T[] target;
// Builder to enable from... to... syntax and
// to make Mapper immutable
public static class Builder<S2 extends Comparable<S2>> {
private final S2[] data;
private Builder(final S2[] data){
this.data = data;
}
public <T2> Mapper<S2, T2> to(final T2... target){
return new Mapper<S2, T2>(this.data, target);
}
}
private Mapper(final S[] source, final T[] target){
final S[] copy = Arrays.copyOf(source, source.length);
Arrays.sort(copy);
this.source = copy;
this.target = Arrays.copyOf(target, target.length);
}
// Factory method to get builder
public static <U extends Comparable<U>, V> Builder<U> from(final U... items){
return new Builder<U>(items);
}
// Map a collection of items
public Collection<T> mapAll(final Collection<? extends S> input){
final Collection<T> output = new ArrayList<T>(input.size());
for(final S s : input){
output.add(this.map(s));
}
return output;
}
// map a single item
public T map(final S input){
final int sourceOffset = Arrays.binarySearch(this.source, input);
return this.target[
Math.min(
this.target.length-1,
sourceOffset < 0 ? Math.abs(sourceOffset)-2:sourceOffset
)
];
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:最后用更高效(更短)的版本替换了map()方法.我知道:对于大型阵列,搜索分区的版本仍然会更快,但抱歉:我太懒了.
如果您认为这太过臃肿,请考虑以下事项:
当然,所有这些功能都可以轻松删除,但代码不太完整,可用性较低或稳定性较差.
我的评论能力尚未开启,希望没有人会根据我的回答"正确地"说出来......
漂亮的丑陋代码可以/应该被定义为试图实现:
IMO org.life.java给出的答案是最漂亮的,非常容易阅读.出于阅读和表现的原因,我也喜欢写条件的顺序.
看看关于这个主题的所有评论,在我写作的时候,似乎只有org.life.java提出了性能问题(也许mfloryan,也说明了某些东西会"更长").当然在大多数情况下,并且在这个例子中它不应该明显减慢但是你写它.
但是,通过嵌套条件并最佳地排序条件可以提高性能[值得,特别是如果这是循环的].
所有这一切,通过确定尽可能快地执行所带来的嵌套和排序条件(比您的示例更复杂)通常会产生不太可读的代码,并且代码更难以改变.我再次提到#3,实用主义......平衡需求.