(Java)如何解析具有多种可能格式的坐标字符串,并将其转换为整数?

时间:2018-09-09 23:19:15

标签: java string parsing format coordinates

我有一个方法可以从用户那里获取(X,Y)坐标字符串。 X和Y坐标的范围都从0到8,并且坐标可以是五种可能的格式之一:

  • (4,3):括号中的X和Y坐标,以逗号分隔且没有空格
  • 4 3 :X和Y坐标仅由空格分隔,无括号
  • 4,3 :X和Y坐标仅用逗号分隔,没有括号
  • d 3 :X以字母表示。 0 = A,1 = B,...,8 = H。 X和Y以空格分隔
  • d3 :与上面相同,除了没有空格。

我遇到的麻烦是开发一种可以成功解析所有四种格式的方法。更具体地说,我想将X和Y坐标都成功转换为两个单独的int并将它们存储在某个位置,而不管使用哪种格式。

我对Java有点陌生,并且对解析字符串没有太多经验。任何指针将不胜感激。

3 个答案:

答案 0 :(得分:1)

您可以按照以下步骤进行操作:

  • 删除所有非数字或字母的字符,您将以2个字符结尾
  • 看两个:
    • 如果数字:解析为int
    • 如果不删除字符代码'a'并添加+1以获得 a = 1,b = 2,...
private static int[] parseToCoord(String s) {
    String[] xy = s.replaceAll("[^\\w\\d]", "").toLowerCase().split("");
    int[] res = new int[2];
    res[0] = xy[0].matches("\\d") ? Integer.parseInt(xy[0]) : xy[0].charAt(0) - 'a' + 1;
    res[1] = xy[1].matches("\\d") ? Integer.parseInt(xy[1]) : xy[1].charAt(0) - 'a' + 1;
    return res;
}

Stream版本是

private static int[] parseToCoordStream(String s) {
    return Stream.of(s.replaceAll("[^\\w\\d]", "").toLowerCase().split(""))
            .mapToInt(val -> val.matches("\\d") ? Integer.parseInt(val) : val.charAt(0) - 'a' + 1)
            .toArray();
}

使用

public static void main(String args[]) throws Exception {
    for (String s : Arrays.asList("(4,3)", "4 3", "4,3", "d 3", "d3", "D3")) {
        int[] xy = parseToCoord(s);
        System.out.println(xy[0] + " " + xy[1]);
    }
}

答案 1 :(得分:0)

首先让我们考虑一个主格式。我们想要将所有这些转换为一种格式,以便最终将它们转换为两个整数。让我们将此格式设置为两个数字,并用空格分隔。这是IMO最容易解析的。

然后,让我们考虑一下所有这些共享的模式。例如,保证第一个输入仅包含一个括号,因此我们可以轻松地识别出它。第三个被保证包含逗号,但是没有括号。因此,我们可以使用规则将它们分组,如果有逗号,则删除括号(如果有的话),然后用空格替换逗号。

那是3点下来,还有2点要走。

现在,这后两个有什么共同点?他们分享一封信。我们可以使用regex轻松地找到这封信,但稍后再担心。因此,让我们制定一个逻辑规则。

如果该短语没有逗号,      我们检查它是否有字母。如果是这样,我们检查它是否有空格。            如果是这样,我们将以空格分隔,并用整数整数替换字符,正确偏移以表示其在字母表中的位置。            否则,我们使用正则表达式将字母分开,然后执行上述操作。

现在,我们对想要放大的内容有了清晰的认识,让我们尝试自己做。

这就是我在代码中的处理方式。

  public int[] parseXYCoord(String s) {
    String master=s;
    if(s.contains(",")){
        master=master.replace("(","").replace(")","");
        master=master.replace(","," ");
    }else if(master.matches("^[a-z]((\\s[0-8])|[0-8])$")){
        int charValue=master.charAt(0)-'a'+1;
        master=charValue+" "+master.charAt(master.contains(" ")?2:1);


    }
    return parseMaster(master);
}

private int[] parseMaster(String master) {
    if(!master.matches("^[0-8] [0-8]$"))
        throw new IllegalArgumentException("Inputted Number is incorrect!");
    String[] splitMaster=master.split(" ");
    return new int[]{Integer.parseInt(splitMaster[0]),Integer.parseInt(splitMaster[1])};

}

我不太擅长正则表达式。虽然很丑陋,但确实可以完成工作。如果您想学习如何使用正则表达式,请访问网站DebugRegex

使用

进行测试
    System.out.println(Arrays.toString(parseXYCoord("4,3")));
    System.out.println(Arrays.toString(parseXYCoord("4 3")));
    System.out.println(Arrays.toString(parseXYCoord("(4,3)")));
    System.out.println(Arrays.toString(parseXYCoord("d3")));
    System.out.println(Arrays.toString(parseXYCoord("d 3")));

它打印

[4, 3]
[4, 3]
[4, 3]
[4, 3]
[4, 3]

答案 2 :(得分:0)

这是如何实施解决方案的示例。输入经过验证,程序将引发适当的异常。我认为这段代码的某些或大多数方面都可以用于实现解决方案。

该程序从命令提示符运行,如下所示:

> java CoordinateParser "d 7"


示例代码

import java.util.*;

public class CoordinateParser {

    private static final Map<Character, Integer> charIntMap = new HashMap<>();
    static {
        charIntMap.put('a', 0);
        charIntMap.put('b', 1);
        charIntMap.put('c', 2);
        charIntMap.put('d', 3);
        charIntMap.put('e', 4);
        charIntMap.put('f', 5);
        charIntMap.put('g', 6);
        charIntMap.put('h', 7);
        charIntMap.put('i', 8);
    }

    public static void main (String [] args) {

        if (args.length != 1) {
            System.out.println("Program needs input string argument, for example:");
            System.out.println("java CoordinateParser \"d7\"");
            System.out.println("Exiting the program.");
            System.exit(0);
        }

        System.out.println("Input: " + args[0]);

        XYCoordinates xy = new CoordinateParser().getCoordinates(args[0]);
        System.out.println("Co-ordinates: " + xy);
    }

    private XYCoordinates getCoordinates(String input)
            throws NumberFormatException {

        input = input.trim();

        if (input.length() < 2 || input.length() > 5) {
            throw new IllegalArgumentException("Invalid input string length: " + input);
        }

        if (input.length() == 5 && input.startsWith("(") && input.endsWith(")")) {
            return new XYCoordinates(input.substring(1, 2), input.substring(3, 4));
        }

        if (input.length() == 3 && input.contains(",")) {
            return new XYCoordinates(input.substring(0, 1), input.substring(2, 3));
        }       

        if (input.length() == 3 && input.contains(" ")) {
            String x = input.substring(0, 1);
            Integer i = charIntMap.get(x.charAt(0));
            if (i != null) {
                return new XYCoordinates(Integer.toString(i), input.substring(2, 3));
            }
        }           

        if (input.length() == 2) {
            String x = input.substring(0, 1);
            Integer i = charIntMap.get(x.charAt(0));
            if (i != null) {
                return new XYCoordinates(Integer.toString(i), input.substring(1, 2));
            }
        }

        throw new IllegalArgumentException("Invalid input format: " + input);
    }

    /*
     * Inner class represents x and y co-ordinates.
     */
    private class XYCoordinates {

        private int x;
        private int y;

        XYCoordinates(String xStr, String yStr) 
                throws NumberFormatException {

            try {
                x = Integer.parseInt(xStr);
                y = Integer.parseInt(yStr);
            }
            catch (NumberFormatException ex) {
                throw new NumberFormatException("Invalid co-ordinates: " +
                    new StringJoiner(", ", "(", ")")
                        .add(xStr).add(yStr).toString());
            }

            if (isNotValidValue(x) || isNotValidValue(y)) {
                throw new IllegalArgumentException("Co-ordinates out of range: " + toString());
            }
        }

        private boolean isNotValidValue(int i) {
            return (i < 0 || i > 8);
        }

        int getX() {
            return x;
        }

        int getY() {
            return y;
        }

        @Override
        public String toString() {
            return new StringJoiner(", ", "(", ")")
                .add(Integer.toString(x))
                .add(Integer.toString(y))
                .toString();
        }
    }
}


XYCoordintes类

在这种情况下,POJO(普通的旧Java对象)表示由类XYCoordinates(具有一组坐标xy定义的对象)。拥有POJO的优点是:

  • 一个人可以轻松地检索各个坐标;例如, getX()getY()
  • 获取坐标的字符串表示形式-通过覆盖 从toString继承的java.lang.Object方法。
  • 通过覆盖两个比较相同(或相等)的坐标 Object类的equals方法(两组具有相同x的坐标 和y的值可能相等)。
  • 将一些坐标存储在集合中并有效地检索它们 (重写Object类的hashcode方法会有所帮助)。

这些是其中的一些优点。另外,可以根据需要为POJO类定义其他属性或行为。比较两个坐标并排序一组坐标就成为我的想法(记住ComparableComparator功能接口)。