让GPT帮你写代码——实现复杂字符串解析

305 阅读2分钟

我的需求

现有的字符串格式如下:

{"attrKey1:value1,attrKey2:value2"}

格式规范: 该字符串是产品属性对。 一个产品有多种属性。 在此格式中,每个属性和属性值均以逗号分隔。 每个属性对都有两部分,左边是属性key,右边是属性value。 左边和右边用冒号分隔。

请使用Java语言实现一个以产品属性集合作为输出参数的方法。

注意:属性值中可能有逗号,例如产品价格:$1,000

为了获得更精准的答案,我把上面这一段翻译成英文,然后把需求提给GPT(使用GPT4)。在需求前,我加了一个角色认定,让GPT作为Java程序员(Suppose you are a Java programmer)

Suppose you are a Java programmer
The existing string format is as follows, separated by ```

{"attrKey1:value1,attrKey2:value2"}

Format specification:
The string is the product attribute pair. A product has multiple attributes. In this format, each attribute and attribute value are separated by commas. Each attribute pair has two parts, the left is the attribute key, and the right is the attribute value. the left and right are separated by colons.

Please use the Java language to implement a method that takes the product attribute set as the output parameter.

Note: There may be commas in attribute values, such as product price: $1,000

ps:不要畏惧英文,Google翻译一下就搞定😄

GPT沟通过程

正则表达式解法

问: image.png 答: image.png

GPT的回答分为三段

① 特意说明了在属性值可能包含逗号的情况下,采用简单的分隔字符串的方式是行不通的。它将使用正则表达式的方式实现。这一点还挺有意思。

② 具体实现代码

③ 对代码的具体说明

一顿操作猛如虎,结果答案是错的!

问:用attrKey1:value1, extra, attrKey2:value2,888, attrKey3:value3测试一下,结果不符合预期

Untitled (2).png

GPT意识到之前的正则有问题,更新了正则表达式

答:

Untitled (3).png

这次OK了,为了确保程序没问题,接着我让他帮我构造了测试用例,GPT给了三个测试字符串,此处省略详细的代码:

String test1 = "attrKey1:value1,extra,attrKey2:value2,888,attrKey3:value3";
String test2 = "product price:$1,000,product weight:1000g,product color:red,blue";
String test3 = "id:123,name:John Doe,email:john.doe@example.com,role:admin,dev";

输出结果如下:

Test Case 1:
attrKey1 : value1,extra
attrKey2 : value2,888
attrKey3 : value3

Test Case 2:
product price : $1,000
product weight : 1000g
product color : red,blue

Test Case 3:
id : 123
name : John Doe
email : john.doe@example.com
role : admin,dev

到此,一段需求实现完成了,但是我还有些不满意,正则表达式的可读性太差了,让他换一种方式实现

字符串解析法

冒号分割解析法

正则表达式的实现方式体现不出GPT4的水平,为了增加难度,要求GPT4换一种方式实现。

问:

Untitled (4).png

答:

给出实现代码

import java.util.*;

public class Main {
    public static void main(String[] args) {
        testParseAttributes();
    }

    public static void testParseAttributes() {
        String test1 = "attrKey1:value1,extra,attrKey2:value2,888,attrKey3:value3";
        String test2 = "product price:$1,000,product weight:1000g,product color:red,blue";
        String test3 = "id:123,name:John Doe,email:john.doe@example.com,role:admin,dev";

        System.out.println("Test Case 1:");
        printAttributes(test1);

        System.out.println("Test Case 2:");
        printAttributes(test2);

        System.out.println("Test Case 3:");
        printAttributes(test3);
    }

    public static void printAttributes(String attributes) {
        Map<String, String> attributeMap = parseAttributes(attributes);
        attributeMap.forEach((key, value) -> System.out.println(key + " : " + value));
    }

    public static Map<String, String> parseAttributes(String attrString) {
        Map<String, String> attributes = new LinkedHashMap<>();

        int prevIndex = 0;
        int separatorIndex = attrString.indexOf(':', prevIndex);

        while (separatorIndex != -1) {
            int nextSeparatorIndex = attrString.indexOf(':', separatorIndex + 1);
            String key, value;
            
            if (nextSeparatorIndex != -1) {
                int commaIndexBeforeNext = attrString.lastIndexOf(',', nextSeparatorIndex);
                key = attrString.substring(prevIndex, separatorIndex).trim();
                value = attrString.substring(separatorIndex + 1, commaIndexBeforeNext).trim();
                prevIndex = commaIndexBeforeNext + 1;
            } else {
                key = attrString.substring(prevIndex, separatorIndex).trim();
                value = attrString.substring(separatorIndex + 1).trim();
            }
            
            attributes.put(key, value);
            separatorIndex = nextSeparatorIndex;
        }
        return attributes;
    }
}

Untitled (5).png

GPT4给出了实现思路,这大段文字看起来太费劲,我们直接看代码。从代码逻辑上看起来是先通过找到冒号,然后再分别解析key和value,不管结果对不对,起码思路是正确的。

滑动窗口双指针解析法

来点更高级的, 我们让GPT优化一下实现方式

答:

Untitled (6).png

GPT选择了滑动窗口的方式,同时用双指针遍历,厉害了👍🏻

import java.util.*;

public class Main {
    public static void main(String[] args) {
        testParseAttributes();
    }

    public static void testParseAttributes() {
        String test1 = "attrKey1:value1,extra,attrKey2:value2,888,attrKey3:value3";
        String test2 = "product price:$1,000,product weight:1000g,product color:red,blue";
        String test3 = "id:123,name:John Doe,email:john.doe@example.com,role:admin,dev";

        System.out.println("Test Case 1:");
        printAttributes(test1);

        System.out.println("Test Case 2:");
        printAttributes(test2);

        System.out.println("Test Case 3:");
        printAttributes(test3);
    }

    public static void printAttributes(String attributes) {
        Map<String, String> attributeMap = parseAttributes(attributes);
        attributeMap.forEach((key, value) -> System.out.println(key + " : " + value));
    }

    public static Map<String, String> parseAttributes(String attrString) {
        Map<String, String> attributes = new LinkedHashMap<>();
        int start = 0, end = 0;

        while (end < attrString.length()) {
            while (end < attrString.length() && attrString.charAt(end) != ':') {
                end++;
            }
            String key = attrString.substring(start, end).trim();

            start = ++end;
            while (end < attrString.length() && !(attrString.charAt(end) == ',' && (end + 1 < attrString.length() && attrString.charAt(end + 1) != ' '))) {
                end++;
            }
            String value = attrString.substring(start, end).trim();

            attributes.put(key, value);
            start = ++end;
        }

        return attributes;
    }
}

Untitled (7).png

代码实现说明,太长不看

逗号分割解析法

emmm,我的要求有些多,上面的方式对我来说太复杂了点,有没有简单点的?

答:

Untitled (8).png

GPT首先解析逗号,然后再分别计算出key和value,和先解析冒号方式类似,不再赘述

import java.util.*;

public class Main {
    public static void main(String[] args) {
        testParseAttributes();
    }

    public static void testParseAttributes() {
        String test1 = "attrKey1:value1,extra,attrKey2:value2,888,attrKey3:value3";
        String test2 = "product price:$1,000,product weight:1000g,product color:red,blue";
        String test3 = "id:123,name:John Doe,email:john.doe@example.com,role:admin,dev";

        System.out.println("Test Case 1:");
        printAttributes(test1);

        System.out.println("Test Case 2:");
        printAttributes(test2);

        System.out.println("Test Case 3:");
        printAttributes(test3);
    }

    public static void printAttributes(String attributes) {
        Map<String, String> attributeMap = parseAttributes(attributes);
        attributeMap.forEach((key, value) -> System.out.println(key + " : " + value));
    }

    public static Map<String, String> parseAttributes(String attrString) {
        Map<String, String> attributes = new LinkedHashMap<>();
        List<String> segments = new ArrayList<>(Arrays.asList(attrString.split(",")));
        int segmentIndex = 0;
        while (segmentIndex < segments.size()) {
            String segment = segments.get(segmentIndex);
            int colonIndex = segment.indexOf(':');
            if (colonIndex >= 0) {
                // Extract attribute key
                String key = segment.substring(0, colonIndex).trim();
                segment = segment.substring(colonIndex + 1);

                // Append the rest of the value segments
                while (segmentIndex + 1 < segments.size() && !segments.get(segmentIndex + 1).contains(":")) {
                    segmentIndex++;
                    segment += "," + segments.get(segmentIndex);
                }
                
                // Add attribute to map
                attributes.put(key, segment.trim());
            }
            segmentIndex++;
        }
        return attributes;
    }
}

至此,多种方式实现了需求,总计耗时30分钟,如果是你写的话,需要多久呢?

最后,不得不说,GPT4太强大了(在GPT3.5上试过同样的问题,不在一个层级上,不赘述),打工人们要充分利用起来