1. 正则表达式编写

任务: 从特定格式字符串中转换出想要的数据结构

字符串示例:

(1002||1003)||(1001||1007)&&(1006&&1004||1033&&1020&&1048)

解析输出示例:

[
    {
        "ruleGroupItem": [
            {
                "ruleValue": "1002",
                "relation": ""
            },
            {
                "ruleValue": "1003",
                "relation": "2"
            }
        ],
        "relation": ""
    },
    {
        "ruleGroupItem": [
            {
                "ruleValue": "1001",
                "relation": ""
            },
            {
                "ruleValue": "1007",
                "relation": "2"
            }
        ],
        "relation": "2"
    },
    {
        "ruleGroupItem": [
            {
                "ruleValue": "1006",
                "relation": ""
            },
            {
                "ruleValue": "1004",
                "relation": "1"
            },
            {
                "ruleValue": "1033",
                "relation": "2"
            },
            {
                "ruleValue": "1020",
                "relation": "1"
            },
            {
                "ruleValue": "1048",
                "relation": "1"
            }
        ],
        "relation": "1"
    }
]

以下为跟chatgpt对话过程:


正则表达式

来自你的消息:

你是一个javascrip代码助手,帮我实现从特定格式字符串中提取出特定格式的数据结构
提取的字符串例子:(1002||1003)||(1001||1007)&&(1006&&1004||1033&&1020&&1048),
其中:
每组括号里都是一个条件表达式,该表达式中的字符除去条件运算符以外只能是数字或者英文字母,该条件表达式的条件运算符只会有&& 跟||
每组括号之间都只是条件运算符,条件运算符也只会有&& 跟||


编写一个正则表达式,提取每个被括号包裹的字符串,以及每组括号间的字符, 输出结构为:
    [
        {
            "ruleGroupItem": [
                {
                    "ruleValue": "1002",
                    "relation": ""
                },
                {
                    "ruleValue": "1003",
                    "relation": "2"
                }
            ],
            "relation": ""
        },
        {
            "ruleGroupItem": [
                {
                    "ruleValue": "1001",
                    "relation": ""
                },
                {
                    "ruleValue": "1007",
                    "relation": "2"
                }
            ],
            "relation": "2"
        },
        {
            "ruleGroupItem": [
                {
                    "ruleValue": "1006",
                    "relation": ""
                },
                {
                    "ruleValue": "1004",
                    "relation": "1"
                },
                {
                    "ruleValue": "1033",
                    "relation": "2"
                },
                {
                    "ruleValue": "1020",
                    "relation": "1"
                },
                {
                    "ruleValue": "1048",
                    "relation": "1"
                }
            ],
            "relation": "1"
        }
    ]

ruleGroupItem代表每个被括号包裹的内容
relation字段取值逻辑:按照条件操作符(条件操作符有&& 跟||)映射出对应的值,&& 取值 1 ,||取值 2, 但是,第一组括号对应的relation字段取值为空字符串

ruleGroupItem.item. ruleValue代表括号内的按照条件操作符分割出来的内容(条件操作符有&& 跟||),
ruleGroupItem.item. relation 按照条件运算符映射出对应的值,&& 取值 1 ,||取值 2, 但是,第一组括号对应的relation字段取值为空字符串

来自 ChatGPT 的消息:

你可以使用以下代码来实现从特定格式字符串中提取出特定格式的数据结构:

const str = "(1002||1003)||(1001||1007)&&(1006&&1004||1033&&1020&&1048)";

// 定义正则表达式匹配每个被括号包裹的字符串
const regex = /\((.*?)\)/g;

// 定义映射关系函数
const getRelationValue = (operator) => {
  if (operator === "&&") {
    return "1";
  } else if (operator === "||") {
    return "2";
  }
  return "";
};

// 定义结果数组
const result = [];

// 匹配每个被括号包裹的字符串
let match;
while ((match = regex.exec(str)) !== null) {
  const groupStr = match[1];
  const groupArr = groupStr.split(/&&|\|\|/);
  const ruleGroupItem = [];
  let relation = "";
  groupArr.forEach((item, index) => {
    const operator = groupStr.charAt(item.length + index);
    const ruleValue = item.trim();
    const itemObj = {
      ruleValue,
      relation: getRelationValue(operator),
    };
    ruleGroupItem.push(itemObj);
    if (index === 0) {
      relation = getRelationValue(operator);
    }
  });

  result.push({
    ruleGroupItem,
    relation,
  });
}

console.log(result);

运行以上代码,你会得到期望的输出结果。

来自你的消息:

得到的结果中relation字段均为空字符串,不符合预期

来自 ChatGPT 的消息:

抱歉,出现了一些错误。在提取关系时,我没有正确地获取每个规则值后的操作符。请使用以下修正后的代码:

const str = "(1002||1003)||(1001||1007)&&(1006&&1004||1033&&1020&&1048)";

// 定义正则表达式匹配每个被括号包裹的字符串
const regex = /\((.*?)\)/g;

// 定义映射关系函数
const getRelationValue = (operator) => {
  if (operator === "&&") {
    return "1";
  } else if (operator === "||") {
    return "2";
  }
  return "";
};

// 定义结果数组
const result = [];

// 匹配每个被括号包裹的字符串
let match;
while ((match = regex.exec(str)) !== null) {
  const groupStr = match[1];
  const groupArr = groupStr.split(/&&|\|\|/);
  const ruleGroupItem = [];
  let relation = "";
  let index = 0;
  for (let i = 0; i < groupArr.length; i++) {
    const item = groupArr[i].trim();
    const itemLength = item.length;
    const operator = groupStr.charAt(index + itemLength);
    index += itemLength + operator.length;
    const ruleValue = item;
    const itemObj = {
      ruleValue,
      relation: getRelationValue(operator),
    };
    ruleGroupItem.push(itemObj);
    if (i === 0) {
      relation = getRelationValue(operator);
    }
  }

  result.push({
    ruleGroupItem,
    relation,
  });
}

console.log(result);

运行修正后的代码,你将得到正确的输出结果。

以上为跟chatgpt对话


分析

重新给出的代码还是不符合预期,relation字段还是空的,于是人工检查给出的代码,发现两个问题: 第一是提取条件运算符的逻辑有问题,如下代码:

const operator = groupStr.charAt(index + itemLength);

应该使用substr而不是charAt,修改为:

const operator = groupStr.substr(groupStr.indexOf(item) - 2, 2)

第二是外层数组的relation字段应该单独按同样的逻辑提取,而不是在groupArr的循环里提取,对生成的代码稍做修改,修改如下:

const str = "(1002||1003)||(1001||1007)&&(1006&&1004||1033&&1020&&1048)";

// 定义正则表达式匹配每个被括号包裹的字符串
const regex = /\((.*?)\)/g;

// 定义映射关系函数
const getRelationValue = (operator) => {
  if (operator === "&&") {
    return "1";
  } else if (operator === "||") {
    return "2";
  }
  return "";
};

// 定义结果数组
const result = [];

// 匹配每个被括号包裹的字符串
let match;
while ((match = regex.exec(str)) !== null) {
  const groupStr = match[1];
  const groupArr = groupStr.split(/&&|\|\|/);
  const ruleGroupItem = [];
    const op = str.substr(str.indexOf(match[0]) - 2, 2)
  let relation = getRelationValue(op);
  groupArr.forEach((item, index) => {

    const ruleValue = item.trim();
      const operator = groupStr.substr(groupStr.indexOf(item) - 2, 2)
    const itemObj = {
      ruleValue,
      relation: getRelationValue(operator),
    };
    ruleGroupItem.push(itemObj);
  });

  result.push({
    ruleGroupItem,
    relation,
  });
}

console.log(result);

如图所示,上述代码已经可以工作了。 rule-group-value-parse.png

总结

chatgpt能很好的帮助我们实现一些代码,前提是提示给的足够准确,在chatgpt给出代码实现以后,如果运行不符合结果可以尝试调整提示,或者手动检查生成的代码并修改相关问题。