在Javascript中将字符串转换为对象

时间:2018-01-27 22:47:23

标签: javascript

我无法使用某个映射转换字符串。我想要转换的字符串如下:

输入

$B$O$TT$O$$KK$$Z$HH$$U$PP$$QQ$U$Z$B$

可以更好地看作以下内容(非常接近HTML):

$B
  $O
    $TT$
  O$
  $K
  K$
  $Z
    $HH$
    $U
      $PP$
      $QQ$
    U$
  Z$
B$

我的目标是将其转化为以下内容:

预期结果

{
  "v": "B",
  "chld": [
    {
      "v": "O",
      "chld": [
        {
          "v": "T"
        }
      ]
    },
    {
      "v": "K"
    },
    {
      "v": "Z",
      "chld": [
        {
          "v": "H"
        },
        {
          "v": "U",
          "chld": [
            {
              "v": "P"
            },
            {
              "v": "Q"
            }
          ]
        }
      ]
    }
  ]
}

我得到的地方:

function transform(contentString, currentObj, currentChld) {
  let closeOpen = {
    open: /\$[A-Z]/i,
    closed: /[A-Z]\$/i 
  }

  if (!contentString.length) {
    return currentObj
  }

  let currentSlice = contentString.slice(0, 2)
  let newString = contentString.substring(2)
  //See if tag is open, for example $A is open, A$ is closed
  if (currentSlice.match(closeOpen['open'])){
    currentObj = {v: currentSlice[1]}
    currentObj.chld = []
    return transform(newString,  currentObj , currentChld)

  }

}

似乎递归并不是很有效。解决方案不一定要递归。如果有更简单的东西也没关系!我希望得到上面的预期结果。有人可以帮忙吗?最简单的解决方案是最好的!

编辑:是的标签只有一个字母,仅限于[A-Z]

中的字母

3 个答案:

答案 0 :(得分:4)

我迟到了,但是一个简单的基于堆栈的appraoch工作得很好。

export class ApiService {

    private selectedCode = new Subject<any>(); // holds reference to clicked item in list
    codeSelected= this.selectedCode.asObservable(); // subscribe

    constructor(private http: HttpClient) {}
    getCodes() {
        return this.http.get('http://localhost:58561/api/codes');
    }
    postCode(code) {
        this.http.post('http://localhost:58561/api/codes', code).subscribe(res => {
            console.log(res)
        })
    }
    selectCode(code) {
        this.selectedCode.next(code)
    }
}

答案 1 :(得分:1)

您可以编写一个PEG.js解析器来为您创建树:

class Node {
  constructor (tag, children = []) {
    this.v = tag;
    if (children.length > 0) {
      this.chld = children;
    }
  }
  toString () {
    return '$' + this.v + (this.chld || []).join('') + this.v + '$'
  }
}

let parser = PEG.buildParser(`
Expression = open:Open children:Expression * close:Close {
  var object = new Node(open, children);

  if (open !== close) {
    return expected('"' + object + '"');
  }

  return object
}

Open = "$" tag:Tag { return tag } 
Close = close:Tag "$" { return close }
Tag = [A-Za-z]
`, { cache: true });

let tree = parser.parse('$B$O$TT$O$$KK$$Z$HH$$U$PP$$QQ$U$Z$B$');

console.log(tree);

try {
  parser.parse('$B$O$TT$$U$PP$V$O$B$');
} catch (error) {
  console.log(error.message);
}
.as-console-wrapper{max-height:100%!important}
<script src="https://cdnjs.cloudflare.com/ajax/libs/pegjs/0.9.0/peg.min.js"></script>

请注意,在版本0.10中,根据documentation,该方法已从peg.buildParser()更改为peg.generate()

答案 2 :(得分:0)

这是一个将结构构建为字符串的简单循环,然后使用JSON解析器将其转换为对象:

const ip = "$B$O$TT$O$$KK$$Z$HH$$U$PP$$QQ$U$Z$B$"

function transform(contentString) {
    let op = "";
    for(var i = 0; i < contentString.length - 3; i += 2) {
        if (contentString[i] === "$") {
            op += `{"v":"${contentString[i+1]}"`;
            if (contentString[i+2] === "$") {
                op += `,"chld":[`;
            }
        } else {
            op += "}";
            if (contentString[i+2] === "$") {
                op += ",";
            } else {
                op += "]";
            }
        }
    }
    return JSON.parse(op + "}");
}

console.log(transform(ip));

注意没有语法检查;代码假定输入字符串是格式良好的结构。