Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

第 152 题:实现一个 normalize 函数,能将输入的特定的字符串转化为特定的结构化数据 #331

Open
gauseen opened this issue Dec 31, 2019 · 46 comments

Comments

@gauseen
Copy link

gauseen commented Dec 31, 2019

字符串仅由小写字母和 [] 组成,且字符串不会包含多余的空格。
示例一: 'abc' --> {value: 'abc'}
示例二:'[abc[bcd[def]]]' --> {value: 'abc', children: {value: 'bcd', children: {value: 'def'}}}

@gauseen gauseen changed the title 实现一个 normalize 函数,能将输入的特定的字符串转化为特定的结构化数据 【阿里笔试】实现一个 normalize 函数,能将输入的特定的字符串转化为特定的结构化数据 Dec 31, 2019
@gauseen gauseen changed the title 【阿里笔试】实现一个 normalize 函数,能将输入的特定的字符串转化为特定的结构化数据 第 152 题:【阿里笔试】实现一个 normalize 函数,能将输入的特定的字符串转化为特定的结构化数据 Dec 31, 2019
@Nolaaaaa
Copy link

Nolaaaaa commented Jan 2, 2020

let normalize = str => {
  let result = {}
  let c
  
  // 字符串转化为数组
  let arr = str.split(/[\[\]]/g).filter(Boolean)
  
  // 生成结构化数据
  arr.forEach((item, index) => {
    if(index != 0) {
      c.children = {}
      c.children.value = item
      c= c.children
    } else {
      result.value = item
      c= result
    }
  })
  
  return result
}
let str = '[abc[bcd[def]]]'
normalize(str)
// {value: 'abc', children: {value: 'bcd', children: {value: 'def'}}}

@linbinhuang
Copy link

linbinhuang commented Jan 2, 2020

const normalize = (str) => {
  var result = {}
  str.split(/[\[\]]/g).filter(Boolean).reduce((obj, item, index, a) => {
    obj.value = item
    if(index !== a.length -1) {
      return (obj.children = {})
    }
  }, result)
  return result
}

@flyfox11
Copy link

flyfox11 commented Jan 6, 2020

function normalize(str) {
	let arr = str.match(/\w+/g)
	let temp = {}
	let obj
	while(arr.length) {
		let item = arr.pop()
		temp.value = item
		obj && (temp.children = obj)
		if(arr.length) {
			obj = {...temp}
			temp = {}
		}else {
			obj = temp
		}
	}
	return obj
}

@quanibm
Copy link

quanibm commented Jan 7, 2020

const normalize = str => {
  const arr = str.split(/[\[\]]/).filter(Boolean);
  const createArr = arr => {
    return arr.reduce((obj, val, n, arr) => {
      arr.length > 1 ? (obj.children = createArr(arr.slice(1))) : "";
      obj.value = arr[0];
      return obj;
    }, {});
  };
  return createArr(arr);
};

@gauseen
Copy link
Author

gauseen commented Jan 7, 2020

var normalize = (str) => {
  var list = str.match(/\w+/g)
  var obj = {}
  var curr = obj
  while (key = list.shift()) {
      curr.value = key
      if (list.length === 0) break
      curr.children = {}
      curr = curr.children
  }
  return obj
}

@yygmind yygmind changed the title 第 152 题:【阿里笔试】实现一个 normalize 函数,能将输入的特定的字符串转化为特定的结构化数据 第 152 题:实现一个 normalize 函数,能将输入的特定的字符串转化为特定的结构化数据 Jan 8, 2020
@yygmind
Copy link
Contributor

yygmind commented Jan 8, 2020

字符串仅由小写字母和 [] 组成,且字符串不会包含多余的空格。
示例一: 'abc' --> {value: 'abc'}
示例二:'[abc[bcd[def]]]' --> {value: 'abc', children: {value: 'bcd', children: {value: 'def'}}}

@XiaoDHuang
Copy link

let normalize = (str) => {
    let arr = str.split(/[\[\]]/).filter(Boolean);
    let i = 0, obj = {}, cur = obj;
    while(i < arr.length) {
        if (i > 0) cur = cur.children = {};
        cur.value = arr[i];
        i ++;
    }

    return obj;
}

@lhyt
Copy link

lhyt commented Feb 2, 2020

function normalize(str, res = {}) {
  if (str) {
    if (str[0] === "[") {
      const exec = /^\[(\w+)(\[.*\]){0,1}\]$/.exec(str);
      if (exec) {
        const [, value, next] = exec;
        res.value = value;
        next && normalize(next, (res.children = {}));
      }
    } else if (!/(\[|\])/.test(str)) {
      res.value = str;
    }
  }
  return res;
}

// 测试用例
[
  "[a[b[c]]]",
  "",
  "asd",
  "[aads",
  "asdasd]",
  "[asddd]",
  "[a[d]",
  "[s[]]"
].reduce((acc, c) => ((acc[c] = normalize(c)), acc), {});

es5、纯算法:

function normalize(str) {
  if (!/(\[|\])/.test(str)) {
    return { value: str };
  }
  var len = str.length,
    quene = [],
    res = {},
    ret = res,
    current = "";
  for (var i = 0; i < len; i++) {
    var c = str[i];
    if (c === "[" || c === "]") {
      if (current) {
        quene.push(current);
        current = "";
      }
      if (c === "]") {
        var top = quene.shift();
        if (top) {
          res.value = top;
          if (quene.length) {
            res = res.children || (res.children = {});
          }
        }
      }
    } else {
      current += c;
    }
  }
  return ret;
}

@kukuxi
Copy link

kukuxi commented Mar 1, 2020

function normalize(str) {
  if (!str) return {};
  const arr = str
    .split(/[\[\]]/g)
    .filter(Boolean)
    .reverse();
  return arr.reduce((acc, cur) => {
    const temp = {};
    if (acc.value) { //说明此时acc !== {}
      temp.children = acc;
    }
    temp.value = cur;
    return temp;
  }, {});
}

@jwdzzhz777
Copy link

function normalize(str) {
  let current, result;
  while (current = str.match(/\[([a-z]+)\]/)) {
    let [res, value] = current;
    result = result ? { value, children: result } : { value };
    str = str.replace(res, '');
  }
  if (!result) result = {value: str};
  return result;
}

@leonwens
Copy link

leonwens commented Mar 23, 2020

function normalize(str) {
      const list = str.match(/\w+/g)
      function fn(list) {
        if(list.length === 1){
          return {
            value: list[0]
          }
        }
        let res = {}
        const item = list.shift();
        res = {
          value: item,
          children: fn(list)
        }
        return res
      }
      return fn(list)
 }

@1368725603
Copy link

var str = '[abc[bcd[def]]]';
console.log(fn(str));
function fn(strs) {
	var arr = strs.replace('[', '').replace(/]/g, '').split('[');
	// console.log('arr: ', arr);
	var res = {};
	var pointer = res;
	for (var i = 0; i < arr.length; i ++) {
		pointer.value = arr[i];
		if (i < arr.length - 1) {
			pointer.children = {};
			pointer = pointer.children;
		}
	}
	return res;
}

@sisterAn
Copy link
Collaborator

sisterAn commented Apr 30, 2020

function normalize(s) {
    let arr = s.match(/\w+/g)
    let result
    while(arr.length) {
        let cur = arr.pop()
        let temp = {value: cur}
        if(result) {
            temp.children = result
        }
        result = temp
    }
    return result
}


// 测试
var s = 'abc'
normalize(s) // {value: "abc"}

s = '[abc[bcd[def]]]'
normalize(s) 
// {value: 'abc', children: {value: 'bcd', children: {value: 'def'}}}

更过编程算法题可见 JavaScript-Algorithms

@fariellany
Copy link

 return (obj.children = {})

return (obj.children = {}) 这个啥意思 呀 还是看不懂 为啥

@Edge00
Copy link

Edge00 commented Jun 12, 2020

 return (obj.children = {})

return (obj.children = {}) 这个啥意思 呀 还是看不懂 为啥

简化一下代码,你可以这么理解:

const normalize = (str) => {
  var result = {};
  str
    .split(/[\[\]]/g)
    .filter(Boolean)
    .reduce((obj, item) => {
      obj.value = item;
      let children = {};
      obj.children = children;
      return children;
    }, result);
  return result;
};

@iblq
Copy link

iblq commented Jun 28, 2020

 return (obj.children = {})

return (obj.children = {}) 这个啥意思 呀 还是看不懂 为啥

简化一下代码,你可以这么理解:

const normalize = (str) => {
  var result = {};
  str
    .split(/[\[\]]/g)
    .filter(Boolean)
    .reduce((obj, item) => {
      obj.value = item;
      let children = {};
      obj.children = children;
      return children;
    }, result);
  return result;
};

代码写的6,顶一个,但是用这种极简的骚操作写法是为了减少代码量么,可读性不考虑么😅

@jiashicheng
Copy link

const normalize = str => {
  const arr = str.split(/[\[\]]/).filter(Boolean);
  const createArr = arr => {
    return arr.reduce((obj, val, n, arr) => {
      arr.length > 1 ? (obj.children = createArr(arr.slice(1))) : "";
      obj.value = arr[0];
      return obj;
    }, {});
  };
  return createArr(arr);
};

你用了递归,你的reduce没有任何意义, 但是我没有证据

@dancingTx
Copy link

const normalize = function(str) {
    let res = {}
    str.split(/[\[\]]/).filter(Boolean).reduce((prev, curr, index) => {
        if (index) prev = prev['children'] = {}
        prev['value'] = curr;
        return prev
    }, res)

    return res
}

@daryl-z
Copy link

daryl-z commented Jul 24, 2020

const normalize = (str = '') =>
  str
    .split(/[\[\]]/g)
    .filter(Boolean)
    .reverse()
    .reduce((acc, cur, index) => (!index ? { value: cur } : { value: cur, children: acc }), {});

let str1 = '[abc[bcd[def]]]',
  str2 = 'abc';
console.log(normalize(str1));
console.log(normalize(str2));

@maggie-chen
Copy link

正则真香

const normalize = (str) => {
    const result = {}
    str.match(/(?=\w)\w+/g).reduce((total,current,index,arr)=>{
        total.value = current
        if(index < arr.length -1) {
            return (total.children = {})
        }
    },result)
    return result
}

@gitwillsky
Copy link

都在正则,来个不用正则的:

/**
 * 第 152 题:实现一个 normalize 函数,能将输入的特定的字符串转化为特定的结构化数据
 * 字符串仅由小写字母和 [] 组成,且字符串不会包含多余的空格。
 * 示例一: 'abc' --> {value: 'abc'}
 * 示例二:'[abc[bcd[def]]]' --> {value: 'abc', children: {value: 'bcd', children: {value: 'def'}}}
 *
 * @version 2020-8-11
 */

const CHILDREN_START = Symbol();
const CHILDREN_END = Symbol();
const VALUE = Symbol();
const EOF = Symbol();

function scanner(s) {
  let pos = 0;
  return {
    [Symbol.iterator]() {
      return this;
    },
    next() {
      let token = {
        value: "",
        type: EOF,
        done: true,
      };
      for (; pos < s.length; ) {
        let c = s.charAt(pos++);
        switch (c) {
          case "'":
            continue;
          case "[":
            token.value = "[";
            token.type = CHILDREN_START;
            token.done = false;
            return token;
          case "]":
            token.value = "]";
            token.type = CHILDREN_END;
            token.done = false;
            return token;
          default:
            token.type = VALUE;
            token.done = false;
            token.value += c;
            while (pos < s.length) {
              c = s.charAt(pos++);
              if (["'", "[", "]"].includes(c)) {
                pos--;
                break;
              }
              token.value += c;
            }
            return token;
        }
      }
      return token;
    },
  };
}

function normalize(str) {
  const scan = scanner(str);
  let obj = {};
  let temp = obj;
  for (let v = scan.next(); !v.done; v = scan.next()) {
    switch (v.type) {
      case CHILDREN_START:
        temp.children = {};
        temp = temp.children;
        break;
      case VALUE:
        temp.value = v.value;
        break;
    }
  }
  if (!obj.value) {
    obj = obj.children;
  }
  return obj;
}

console.log(JSON.stringify(normalize("[abc[bcd[def]]]"))); // => {"value":"abc","children":{"value":"bcd","children":{"value":"def"}}}
console.log(JSON.stringify(normalize("abc"))); // => {"value":"abc"}

@wenchao0809
Copy link

/**
 * 递归版本
 * @param {string} str 
 */
export function normalizeRecur(str) {
  const matchRe = /^\[.*\]$/
  const valueRe = /^\[([^\[\]]*)/
  let root = {}
  if (matchRe.test(str)) {
    root.value = str.match(valueRe)[1]
    root.children = normalize(str.slice(1 + root.value.length, str.length - 1))
  } else if (str.length > 0) {
    root.value = str
  } else {
    root = undefined
  }
  return root
}
/**
* 非递归版本
 * @param {string} str 
 */
export function normalize(str) {
  const stack = []
  const  startRe = /^\[/
  const endRe = /^\]/
  const valueRe = /^\[([^\[\]]*)/
  let root
  let parent
  while(str) {
    if(startRe.test(str)) {
      let valueMatch = str.match(valueRe)
      let cur = {}
      root = root || cur
      if (parent) parent.children = cur
      cur.value = valueMatch[1]
      stack.push(cur)
      parent = cur
      str = str.slice(valueMatch[0].length)
    } else if (endRe.test(str)) {
      str = str.slice(1)
      stack.pop()
    }
  }
  return root
}

@carbrokers
Copy link

function normalize(str) {
  var array = str.match(/[a-z]+/g);
  var obj = {};
  array.reduce((acc, cur, index) => {
    const isInLast = index == array.length - 1;
    acc.value = cur;
    if (!isInLast) {
      acc.children = {}
    }
    return isInLast ? acc : acc.children
  }, obj);
  return obj;
}

normalize('abc')
normalize('[abc[bcd[def]]]')

@wabRul
Copy link

wabRul commented Sep 2, 2020

function normalize(str) {
    let len = str.length, stack = [], j = 0
    for (let i = 0; i < len; i++) {
        if (str[i] === '[') {
            j++
        } else if (str[i] === ']') {
            j--
        } else {
            if (!stack[j]) {
                stack[j] = ''
            }
            stack[j] = stack[j] + str[i]
        }
    }
    if (stack.length && stack[0] === undefined) {
        stack.shift()
    }
    let root = {}, temp = root
    for (let i = 0; i < stack.length; i++) {
        temp.value = stack[i]
        if (i !== stack.length - 1) {
            temp.children = {}
            temp = temp.children
        }
    }
    return root
}

@Jerry-RL Jerry-RL mentioned this issue Sep 8, 2020
@Jerry-RL
Copy link

Jerry-RL commented Sep 8, 2020

function normalize(str) {
    let arr = str.split(/[\[\]]/g).filter(Boolean);
    if(arr.length === 1) return {value:arr[0]}
    return arr.reduceRight(function(pre, curr, idx) {
        pre.value = curr
        return idx > 0 ? {chiledren: pre} : pre
    }, {})
}

@brushbird
Copy link

我想说,以上考虑过这种情况么
'[abc[bcd[def]ghi[jkl]]'
还是说这种嵌套的不在考虑范围内

@pan-Z2l0aHVi
Copy link

function normalize(str) {
  const arr = str.split(/[[\]]/).filter(Boolean) // str.split(']').join('').split('[').filter(Boolean)
  return arr.length > 1
    ? arr.reverse().reduce((acc, cur, index) => ({
        value: cur,
        children: index === 1 ? { value: acc } : acc
      }))
    : { value: str }
}

@jdkwky
Copy link

jdkwky commented Jan 18, 2021

function parse(str){
            const list = str.split(/(\[|\])/).filter(val =>val);
            let result = null;
            let temp = null;
            for(let i = 0, len = list.length; i< len; i++){
                const value = list[i];
                if(value == ']'){
                    break;
                }
                
                switch(value){
                    case '[':
                      if(result){
                          result = (result.children || (result.children = {}));
                      }else{
                          result = temp =  {};
                      }
                      break;
                      default: 
                        if(result){
                            result.value = value;
                        }else{
                            result = temp =  { value: value};
                        }
                        break;
                }
                
            }
            return temp;

        }

@xiaowuge007
Copy link

    function normalize(str) {
		let res = str.match(/\[(.+?)\]/);
		let p = res ? res[1] : str;
		let arr = p.split('[');
		var obj = {};
		var cur = obj;
		for (let i = 0; i < arr.length; i++) {
			if (i > 0) {
				cur.children = {value: arr[i]}
				cur = cur.children
			} else {
				cur.value = arr[i];
			}
		}
		return obj;
	}

@Luz-Liu
Copy link

Luz-Liu commented Feb 7, 2021

function normalize(str) {
	let arr = str.split(/[\[\]\s]+/).filter(Boolean);
	let result = {};
	arr.reduce((pre, next) => (pre.children = { value: next }), result);
	return result.children;
}

@negativeentropy9
Copy link

// 字符串仅由小写字母和 [] 组成,且字符串不会包含多余的空格。
// 示例一: 'abc' --> {value: 'abc'}
// 示例二:'[abc[bcd[def]]]' --> {value: 'abc', children: {value: 'bcd', children: {value: 'def'}}}

function format(str) {
    const stack = []
    let i = 0
    let result

    while (i < str.length) {
        switch (str[i]) {
            case "[":
                i++
                break;
            case "]":
                i++
                stack.pop()
                break;
            default:
                let val = str[i];
                i++

                while (!['[', ']'].includes(str[i]) && i < str.length) {
                    val += str[i];
                    i++
                }

                const node = { val };

                if (!stack.length) {
                    result = node
                }

                if (stack.length && stack.length - 1 < stack.length) {
                  stack[stack.length - 1].children =
                    stack[stack.length - 1].children || [];
                  stack[stack.length - 1].children.push(node);
                }

                stack.push(node);
        }
    }

    return result;
}

console.log("format", format("[abc[bcd[def]]]"));
console.log("format", format("[abc[bcd[def][1]][2]]"));

@haipingzi
Copy link

function normalize(str) {
      let obj = {};
      const vals = str.split(/[\[\]]/g).filter(Boolean);
      for (let i = vals.length - 1; i >= 0; i--) {
        !obj.value ? obj.value = vals[i] : obj = {
          value: vals[i],
          children: {
            ...obj
          }
        }
      }
      return obj
    }

@zhelingwang
Copy link

reduce 搞定

function normalize(input) {
  const arr = input.replace(/\[|\]/g, ',').split(',').filter(itm => itm);
  let result = {};
  arr.reduce((obj, cur, idx) => {
    const temp = {};
    temp.value = cur;
    if (obj.children) obj.children = temp;
    if (idx !== arr.length - 1) temp.children = {};
    if (idx === 0) result = temp;
    return temp;
  }, result);
  return result;
}

console.log(normalize('abc'));
console.log(normalize('[abc[bcd[def]]]'));

@JYone223
Copy link

JYone223 commented Aug 5, 2021

用栈实现

function normalize(str) {
  const stack = [];
  let res = {};

  for (let c of str) {
    if (c === ']') {
      let value = [];
      let top = stack.pop();

      while (top !== '[') {
        value.unshift(top);
        top = stack.pop();
      }

      if (res.value) {
        res.children = { ...res };
      }
      res.value = value.join('');
      continue;
    }
    stack.push(c);
  }

  if (stack.length) {
    res.value = stack.join('');
  }

  return res;
}

@dogfeeling
Copy link

es6实现

function normalize(str) {
  let obj = {};
  let arr = str.split(/[\[\]]/g).filter(Boolean);
  arr.reduce((acc, cur) => {
    while (acc.children) {
      acc = acc.children;
    }
    acc.value = cur;
    acc.children = {};
    return acc;
  }, obj);
  return obj;
}

es5实现

function findChild(obj) {
  return obj.children ? findChild(obj.children) : obj;
}

function normalize2(str) {
  let arr = str.split(/[\[\]]/g).filter(Boolean);
  let res = {};
  while ((item = arr.shift())) {
    let obj = findChild(res);
    obj.value = item;
    obj.children = {};
  }
  return res;
}

上面同学的测试用例

let arr = [
  "[a[b[c]]]",
  "",
  "asd",
  "[aads",
  "asdasd]",
  "[asddd]",
  "[a[d]",
  "[s[]]",
];
arr.reduce((acc, c) => ((acc[c] = normalize(c)), acc), {});

@hcd1983
Copy link

hcd1983 commented Dec 13, 2021

reverse 倒著回來

function normalize(str) {
  const arr = str.replaceAll(']', '').split('[').filter(Boolean)
  const res = arr.reverse().reduce((obj, value, idx, a) => {
    if (idx > 0) {
      obj.children = {
        ...obj
      }
    }
    obj.value = value
    return obj
  }, {})
  return res
}

const str = '[abc[bcd[def]]]'
console.log(normalize(str))

@miniflycn
Copy link

function parse(str) {
    let s = str
    const tokens = [
        /^\[/,
        /^\w+/,
        /^\]/
    ]
    let res = {}
    let point = undefined
    let parentMap = new Map()
    while (s) {
        for (let i = 0, l = tokens.length; i < l; i++) {
            let token = s.match(tokens[i])
            if (token) {
                s = s.replace(tokens[i], '')
                switch (i) {
                    case 0:
                        if (!point) {
                            point = res
                            parentMap.set(point, undefined)
                        } else {
                            point.children = {}
                            parentMap.set(point.children, point)
                            point = point.children
                        }
                        break
                    case 1:
                        point.value = token[0]
                        break
                    case 2:
                        point = parentMap.get(point)
                        break
                }
            }
        }
    }
    return res
}

@TheFirstSunday
Copy link

const normalize = (str = '') => {
    const result = {};
    const array = str.split(/[\[\]]/g).filter(Boolean);
    const { length } = array;

    array.reduce((previousValue, currentValue, currentIndex) => {
      previousValue.value = currentValue;
      if(currentIndex !== length - 1) return (previousValue.children = {})
    }, result);
    
    return result;
}

@Yxgm
Copy link

Yxgm commented May 31, 2022

/**
 *
 * @param {string} str
 */
const Normalize = (str) => {
  const obj = Object.create(null);
  const arr = str.match(/\w+/g); //[ 'abc', 'bcd', 'def' ]
  let index = 0;

  (function createObj(obj) {
    obj.value = arr[index++];
    if (index === arr.length) return;
    obj.children = {};
    return createObj(obj.children);
  })(obj);

  console.log(JSON.stringify(obj, undefined, '    '));
  return obj;
};

const Normalize = (str) => {
  const arr = str.match(/\w+/g); //[ 'abc', 'bcd', 'def' ]
  const obj = Object.create(null);

  arr.reduce((pre, current, index) => {
    pre['value'] = current;
    if (index == arr.length - 1) return null;
    pre['children'] = {};
    return pre['children'];
  }, obj);

  return obj;
};

console.log(Normalize('[abc[bcd[def]]]'));

@Yangfan2016
Copy link

function normalize(str) {
    const list = str.split(/[\[\]]/).filter(Boolean); // ['abc','bcd','def']
    const res = {};
    let temp = {};

    for (let i = 0; i < list.length; i++) {
        const item = list[i];
        if (i === 0) {
            res.value = item;
            temp = res;
        } else {
            temp.children = {
                value: item
            };
            temp = temp.children;
        }
    }
    return res;
}

@CHENJIAMIAN
Copy link

CHENJIAMIAN commented Sep 9, 2022

let arr = '[abc[bcd[def[hij]]]]'.match(/\w+/g)
//['abc', 'bcd', 'def']
let obj = {};

let res = {
    val: arr.pop()
};
while (arr.length > 0) {
    res = {
        val: arr.pop(),
        child: res
    };
}

@code-small-white
Copy link

const normalize = (v) => {
    if (v[0] != '[') return { value: v };
    const jsonStr = v.replace(/\[([^\[\]]+)/g, (_, value) => (`"value": "${value}","children":{`))
        .replaceAll(']', '}')
        .replace(',"children":{}', '');
    return JSON.parse(`{${jsonStr}}`);
};

@code-small-white
Copy link

const normalize = (str) => {
    const root = {};
    const holdMap = [];
    let hold = root;
    let floor = 0;
    let subVal = '';
    const setVal = () => {
        if (!subVal) return;
        hold.value = subVal;
        subVal = '';
    };
    for (var c of str) {
        if (c === '[') {
            setVal();
            holdMap[++floor] = hold;
            hold.children = {};
            hold = hold.children;
        } else if (c === ']') {
            setVal();
            hold = holdMap[--floor];
        } else {
            subVal += c;
        }
    }
    setVal();
    return root.value ? root : (root.children || {});
};

@XW666
Copy link

XW666 commented Sep 22, 2023

 const normalize2 = (str) => {
    let arr = str.split(/[\[\]]/g).filter(Boolean)
    let len = arr.length - 1
    var result = {}
//递归的形式
    let fun = (index, obj) => {
      for (let i = index; i < arr.length; i++) {
        obj.value = arr[index]
        if (i !== len) {
          obj.children = {}
          fun(index + 1, obj.children)
        }
      }
    }
    fun(0, result)
  }

@dixinL
Copy link

dixinL commented Sep 27, 2023

function normalize(str) {
  let temp = []
  let valStart = false
  let nowVal = ''
  let obj = {}
  let resKey = ''
  for (let i = 0; i < str.length; i++) {
    if (str[i] == '[') {
      valStart = true
      if (nowVal !== '') {
        obj[nowVal] = {value: nowVal}
        if (temp.length > 0) {
          if (!obj[temp[temp.length - 1]].children) {
            obj[temp[temp.length - 1]].children = []
          }
          obj[temp[temp.length - 1]].children.push(obj[nowVal])
        }
        temp.push(nowVal)
      }
      nowVal = ''
    } else if (str[i] == ']') {
      valStart = false
      if (nowVal !== '') {
        obj[nowVal] = {value: nowVal}
        if (temp.length > 0) {
          if (!obj[temp[temp.length - 1]].children) {
            obj[temp[temp.length - 1]].children = []
          }
          obj[temp[temp.length - 1]].children.push(obj[nowVal])
        }
        temp.push(nowVal)
      }
      if (temp.length == 1) {
        resKey = temp[0]
      }
      temp.pop()
      nowVal = ''
    } else if (valStart) {
      nowVal += str[i]
    }
  }
  return obj[resKey]
}

看起来大部分题解都只能支持逐级的链式结构,以数组方式处理字符串必然会丢失数据的结构化。这样处理数据导致重要参数丢失显然是不够健壮

let str = '[abc[xx[yy][zz]][cc[dd]]]'
console.log(str)
console.log(normalize(str))

可以以栈的方式存储上一级对象名称并根据对象的堆特性,来实现将字符串处理为简单对象的能力。

@keven-wang
Copy link

keven-wang commented Apr 2, 2024

function nomalize(str) {
    const props = str.match(/\w+/g);
    if (props.length === 1) { 
        return { value: props[0] };
    }
    
    return props.reduceRight((children, parent) => {
        if (typeof children === 'string') {
            children = { value: children };
        }
        
        return { value: parent, children };
    });
}
console.log(JSON.stringify(nomalize('abc')));
console.log(JSON.stringify(nomalize('[abc[bcd[def]]]')));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests