You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用JavaScript将含AND/OR逻辑的纯文本转为嵌套JSON对象并优化性能

如何用JavaScript将含AND/OR逻辑的纯文本转为嵌套JSON对象并优化性能

兄弟,我来帮你搞定这个问题!你的现有代码已经有了基础思路,但核心问题是没处理括号的层级关系,也没构建出带AND/OR键的嵌套结构,咱们一步步来调整,同时兼顾性能优化~

一、先搞定核心需求:构建正确的嵌套结构

首先,咱们得明确原字符串的逻辑:顶级是多个用AND连接的项,每个项要么是单个数字(被{}包裹),要么是括号包裹的、用OR连接的数字组。直接用split('AND')会有问题——如果括号里有AND(虽然你例子里没有,但得考虑通用情况),会错误分割括号内的内容。

所以第一步要写一个能忽略括号内内容的顶级运算符分割函数,然后再处理每个项:

function parseCondition(str) {
  // 先一次性去掉所有空格,减少后续处理麻烦
  const cleanStr = str.replace(/\s+/g, '');
  
  // 辅助函数:分割顶级运算符,括号内的内容不参与分割
  function splitTopLevel(s, operator) {
    const result = [];
    let current = '';
    let bracketDepth = 0;
    const opLength = operator.length;
    
    for (let i = 0; i < s.length; i++) {
      const char = s[i];
      // 记录括号深度
      if (char === '(' || char === '{') bracketDepth++;
      if (char === ')' || char === '}') bracketDepth--;
      
      // 只有当括号深度为0时,才匹配顶级运算符
      if (bracketDepth === 0 && s.slice(i, i + opLength) === operator) {
        result.push(current);
        current = '';
        i += opLength - 1; // 跳过运算符的剩余字符
      } else {
        current += char;
      }
    }
    result.push(current);
    return result;
  }
  
  // 分割顶级的AND项
  const andItems = splitTopLevel(cleanStr, 'AND');
  
  // 处理每个AND项,生成对应结构
  const parsedAnd = andItems.map(item => {
    // 去掉项外层的括号/大括号(比如{2109}或(xxx))
    const content = item.replace(/^[\{\(](.*)[\}\)]$/, '$1');
    
    // 如果内容包含OR,说明是OR组,构建{or: [...]}对象
    if (content.includes('OR')) {
      const orItems = splitTopLevel(content, 'OR');
      // 把每个OR项转成数字(去掉可能的{})
      const numbers = orItems.map(numStr => Number(numStr.replace(/[\{\}]/g, '')));
      return { or: numbers };
    } else {
      // 单个数字,直接转成数值
      return Number(content.replace(/[\{\}]/g, ''));
    }
  });
  
  // 最终返回顶级的AND结构
  return { and: parsedAnd };
}

// 测试你的例子
const optionString = '{2109} AND ({2370} OR {1701} OR {2702}) AND {1234} AND ({2245} OR {2339})';
console.log(parseCondition(optionString));

运行后就能得到你想要的结构:

{
  and: [
    2109,
    { or: [2370, 1701, 2702] },
    1234,
    { or: [2245, 2339] }
  ]
}

二、性能优化方案

如果要处理非常长的条件字符串,咱们可以优化几点,提升运行效率:

1. 减少正则表达式的使用

正则虽然方便,但多次调用会有性能开销,咱们可以用遍历的方式提取数字,代替正则替换:

// 替换原来的数字转换逻辑,用这个辅助函数
function extractNumber(str) {
  let numStr = '';
  for (const char of str) {
    // 匹配数字和负号(支持负数场景)
    if (!isNaN(char) || char === '-') {
      numStr += char;
    }
  }
  return Number(numStr);
}

2. 提前预处理,避免重复操作

比如一次性去掉所有空格,而不是每次处理项的时候再trim或替换;缓存运算符的长度,避免循环中重复计算。

3. 直接处理括号,不用正则替换

判断项是否被括号包裹时,直接用字符串的startsWith和endsWith,比正则更快:

// 替换原来的content提取逻辑
let content = item;
if ((content.startsWith('(') && content.endsWith(')')) || (content.startsWith('{') && content.endsWith('}'))) {
  content = content.slice(1, -1);
}

整合后的优化版代码:

function parseConditionOptimized(str) {
  // 一次性去掉所有空格
  const cleanStr = str.replace(/\s+/g, '');
  
  // 辅助函数:分割顶级运算符
  const splitTopLevel = (s, op) => {
    const res = [];
    let current = '';
    let depth = 0;
    const opLen = op.length;
    
    for (let i = 0; i < s.length; i++) {
      const c = s[i];
      if (c === '(' || c === '{') depth++;
      if (c === ')' || c === '}') depth--;
      
      if (depth === 0 && s.slice(i, i + opLen) === op) {
        res.push(current);
        current = '';
        i += opLen - 1;
      } else {
        current += c;
      }
    }
    res.push(current);
    return res;
  };
  
  // 辅助函数:提取字符串中的数字
  const extractNumber = s => {
    let numStr = '';
    for (const c of s) {
      if (!isNaN(c) || c === '-') numStr += c;
    }
    return Number(numStr);
  };
  
  const andItems = splitTopLevel(cleanStr, 'AND');
  
  const parsedAnd = andItems.map(item => {
    // 去掉外层括号/大括号
    let content = item;
    if ((content.startsWith('(') && content.endsWith(')')) || (content.startsWith('{') && content.endsWith('}'))) {
      content = content.slice(1, -1);
    }
    
    if (content.includes('OR')) {
      const orItems = splitTopLevel(content, 'OR');
      return { or: orItems.map(extractNumber) };
    } else {
      return extractNumber(content);
    }
  });
  
  return { and: parsedAnd };
}

三、为什么你的原有代码不行?

你的代码直接用split('AND')分割,会把括号内的内容也错误分割(如果括号里有AND的话);而且只是把结果转成了二维数组,没有根据OR的存在构建对应的{or: [...]}对象,也没有顶级的and键。用上面的方法就能完美解决这些问题啦~

备注:内容来源于stack exchange,提问作者ha kuna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.23 14:37:35