是否有一种优雅的方法可以从字符串中获得两个连续的字符直到拳头数字出现



我想从字符串中获取两个字符(不是数字),直到第一个数字出现。字符串可能是任何,也将包含数字。我只需要注意前两个索引即可。一点棘手的部分是说第二个索引包含一个数字,然后只需要考虑第一个字符。

Examples:
abcd -> ab
a -> a
a0cd -> a
0bcd -> null
-123 -> null

下面是我在Java中编写此功能的方式。还有其他优雅的方式吗?非常感谢任何帮助。

public class Main {
    public static String getFirstTwoCharBeforeDigit(String s) {
        if(null==s||s.length()==0) return null;
        int cropIndex=Math.min(s.length(), 2);      
        if(!Character.isLetter(s.charAt(0))) return null;
        if(cropIndex>1 && !Character.isLetter(s.charAt(1))) --cropIndex;
        return s.substring(0,cropIndex);
    }
    public static void main(String[] args) {
        System.out.println(getFirstTwoCharBeforeDigit("Az-a0"));
    }
}

这似乎有效(谢谢蒂莫西):

private static final java.util.regex.Pattern pattern = Pattern.compile("^[a-z]{1,2}");
private static String getFirstTwoChars(String string) {
    if (string == null) {
        return null;
    }
    java.util.regex.Matcher matcher = pattern.matcher(string);
    return matcher.find() ? matcher.group(0) : null;
}

我建议使用正则表达式,如Pattern类API所述。

"^[a-z]{1,2}"

@RunWith(Parameterized.class)
public class ConsecutiveCharsTest {
    @Parameters
    public static Collection<Object[]> data() {
        //@formatter:off
        return Arrays.asList(new Object[][] {
            {"abcd", "ab" },
            {"a", "a" },
            {"a0bc", "a" },
            {"0bcd", null },
            {"-123", null },
        });
        //@formatter:on
    }
    private final String input;
    private final String expected;
    public ConsecutiveCharsTest(String input, String expected) {
        super();
        this.input = input;
        this.expected = expected;
    }
    @Test
    public void test() {
        Pattern pattern = Pattern.compile("^[a-z]{1,2}");
        Matcher matcher = pattern.matcher(input);
        if (matcher.find()) {
            assertEquals(input, expected, matcher.group());
        } else {
            assertNull("no Match expected", expected);
        }
    }
}

我认为,将RegExp用于此简单任务是太重,因为很多其他对象是在场景后面创建的。我的解决方案不那么可读性,但是它具有更好的性能和最小的其他内存对象的创建:

public static String getFirstTwoCharBeforeDigit(String str) {
    return str != null && !str.isEmpty() ? Character.isAlphabetic(str.charAt(0)) ? str.substring(0, str.length() > 1 && Character.isAlphabetic(str.charAt(1)) ? 2 : 1) : null : null;
} 

只是添加另一种选择:

public static String getFirstTwoCharBeforeDigit(String str) {
    String firstTwo = str.substring(0,Math.min(str.length(), 2)).replaceAll("\d*$", "");
    return firstTwo.chars().allMatch(Character::isLetter) && !firstTwo.isEmpty()? 
           firstTwo:
           null;
}

最新更新