我实施了一个非常简单的方法:
private String getProfileName(String path) {
String testPath = null;
for (int i = 0; i < path.length(); i++) {
testPath = path.substring(0, i);
if ( testPath.endsWith("1") || testPath.endsWith("2") || testPath.endsWith("3") || testPath.endsWith("4") || testPath.endsWith("5") || testPath.endsWith("6") || testPath.endsWith("7") || testPath.endsWith("8") || testPath.endsWith("9") ) {
break;
}
}
return testPath.substring(0, (testPath.length() - 1));
}
我不喜欢整个方法,因为我觉得它比必要的更复杂,特别是if条件。
所以我想到了一种重构这种方法的方法。首先我想用Regex替换if条件,但对于这个简单的情况,是不是正则表达式太多了?
其他任何想法如何重新审视?
答案 0 :(得分:12)
将此模式与匹配器一起使用:
"^[^1-9]*"
示例代码:
private String getProfileName(String path) {
Pattern pattern = Pattern.compile("^[^1-9]*");
Matcher matcher = pattern.matcher(path);
matcher.find();
return matcher.group();
}
我认为这比你的代码更容易理解。我花了几分钟来计算你的逻辑,我必须运行它才能确定。我认为使用正则表达式很清楚代码在做什么。如果您希望可以只编译一次正则表达式,并通过将其移动到类的静态成员来重用它。
正则表达式对Stack Overflow有很大的耻辱(主要来自试图使用它们来解析HTML,电子邮件地址,URL以及各种其他令人讨厌的正则表达式的不当使用的人)。但是对于这种任务,正则表达式就好了。
您可能还想考虑为什么要省略0,如果这是个好主意。
答案 1 :(得分:7)
矿:
private String getProfileName(String path) {
return path.split("[1-9]")[0];
}
希望这会对你有所帮助。
解释。正如Mark Byers所说,数字上的Split(第一个版本,第二个版本忽略0),并返回结果数组的第一个元素。但我认为如果第一个参数是一个数字(用jdk1.6.0_20测试),它不会失败。如果路径中的所有字符都是数字(例如“2223”),则会失败。您可以使用此版本来避免错误:
private String getProfileName(String path) {
String[] result = path.split("[1-9]");
return result.length > 0 ? result[0] : "";
}
正如您将在String's split method javadocs处看到的,它需要一个参数(正则表达式),您可以使用其中一个:
return path.split("[1-9]")[0]; //if you want to avoid 0
return path.split("\\d")[0]; //if you don't
恕我直言:如果您正在寻求提高代码可读性,使用split方法比其他方法更好,
答案 2 :(得分:6)
当然,你可以使用强力进行重构......但为什么不使用Apache Commons?
private String getProfileName(String path) {
int index = StringUtils.indexOfAny(path, "123456789");
if(index != -1) {
return path.substring(0, index);
}
return path;
}
答案 3 :(得分:5)
除了正则表达式:
private static String getProfileName(String path) {
final int len = path.length();
for (int i=0; i<len; ++i) {
char c = path.charAt(i);
if ('1' <= c && c <= '9') {
return i==0 ? "" : path.substring(0, i-1); // Probably don't want that -1 !!
}
}
return len==0 ? "" : path.substring(0, len-1);
}
或者,对于Single Entry,Single Exit粉丝:
private static String getProfileName(String path) {
final int len = path.length();
int i=0;
while (i != len && !isProfileTerminator(path.charAt(i))) {
//Or (!(i == len || isProfileTerminator(path.charAt(i)))) {
++i;
}
return i==0 ? "" : path.substring(0, i-1);
}
private static boolean isProfileTerminator(char c) {
return '1' <= c && c <= '9');
}
原始代码中存在问题,字符串为空或以1-9开头。
答案 4 :(得分:4)
private String getProfileName(String path)
{
int i;
for (i = 0; i < path.length() && !Character.isDigit(path.charAt(i)); i++);
return path.substring(0, i);
}
答案 5 :(得分:3)
我会说与正则表达式一起去。我想不出更简单的重构方法。我可能会想到更多复杂的方式,但我认为你不会想要那样。
答案 6 :(得分:2)
这是一个单行的正则表达式解决方案,非常简单:
private String getProfileName(String path) {
return path.replaceFirst("(?s)\\d.*", "");
}
该模式在Pattern.DOTALL
模式下为\d.*
,为嵌入式标记(?s)
。这将匹配一个数字,以及它之后的所有内容。我们想删除这部分,所以我们用空字符串替换。
请注意,\d
也包含0
,因此如果真的是规范,请替换为[1-9]
。
答案 7 :(得分:1)
您可以创建一个这样的方法放入if
private static boolean endsWith1to9(String a) {
for(int i = 1; i <= 9; i++) {
if(a.endsWith(String.valueOf(i))) {
return true;
}
}
return false;
}
答案 8 :(得分:1)
我觉得这样的事情会起作用。如果我错了,有人会纠正我。
private String getProfileName(String path) {
int i = 0;
for(i = 0; i < path.length; ++i)
{
if(path.charAt(i) > '0' && path.charAt(i) <= '9') break;
}
return path.substring(0, i-1);
}
答案 9 :(得分:1)
我的尝试:
/** * Numeric Register Optimized Search with Null Pointer Handling. * -> No use of Regex (per requirement). :) * -> No use of Character.isDigit() (NOTE: includes characters other than [0-9].) * -> Catch and Avoid NullPointerExceptions (Oops... review other methods above.) * -> Reduce for(...; test ; ...) to while(test) by variable declaration and ++off use. * -> Include ANDed test to avoid break call. * -> Cache "path.length" in local variable (e.g. CPU register) * -> Cache "path.charAt(off)" in local variable (e.g. CPU register) * -> Replace String.endsWith(...) Method with char < char Register Method. * -> Reuse path argument to avoid another internal object reference. * -> Avoid call to substring if [1-9] not found in path. * -> Single Entry/Single Exit Happy. :) * @return path null if passed null, otherwise valid value. */ private String getProfileName(String path) { if (path != null) { int off = -1, len = path.length; final char one = '1', nine = '9'; char c; while (++off < len && (c = path.charAt(off)) < one && c > nine); if (off < len) { path = path.substring(0, off); } } return (path); }干杯, loeJava