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

解析URL字符串 #3

Open
careteenL opened this issue Aug 5, 2019 · 0 comments
Open

解析URL字符串 #3

careteenL opened this issue Aug 5, 2019 · 0 comments
Labels
算法&数据结构 算法&数据结构

Comments

@careteenL
Copy link
Owner

解析字符串

前言

写一个程序parse,解析下面的queryString,返回一个对象

console.log(parse('a=1&b=2&c=3')) // => { a: '1', b: '2', c: '3' }
console.log(parse('a&b&c')) // => {}
console.log(parse('a[name][second]=careteen&a[company]=sohu&b=y')) // => { a: { name: { second: 'careteen' }, company: 'sohu' }, b: 'y' }
console.log(parse('color=Deep%20Blue')) // => { color: 'Deep Blue' }
console.log(parse('a[0]=1&a[1]=2')) // => { a: [ '1', '2' ] }

分析

首先要先了解url参数的规则

  • &或其他字符进行分割,且以=分割键值对
  • &=分割时可能没有值
  • =后面的值可能已经encodeURIComponent转码,需要解码
  • 可能会是一个多层级的对象a[name][second]=careteen&a[company]=sohu&b=y,需要按层级设置对象
  • 对象的键可能为一个数字a[0]=1&a[1]=2,此时应该处理返回成数组

实现

针对上述分析其规则,解析一个URL需要考虑诸多情况。

具体代码和测试用例实现

下面给出具体实现

/**
 * @desc 解析URL
 * @param {String} str 
 * @param {Object} options 
 * @param {String} options.delimiter // 分隔符
 */
const parse = (str, options = {}) => {
  let config = Object.assign({
    delimiter: '&'
  }, options)

  return str.split(config.delimiter).reduce((ret, cur) => {
    let [key, value] = cur.split('=')
    if (!value) return ret
    // ret[key] = value
    deepSet(ret, key, value)
    return ret
  }, {})
}

辅助函数

/**
 * @desc 辅助函数 深层级设置
 */
const deepSet = (ret, key, value) => {
  /* eslint-disable */
  let path = key.split(/[\[\]]/g).filter(item => !!item)
  // console.log(path)
  let i = 0
  for (; i < path.length - 1; i++) {
    if (ret[path[i]] === undefined) {
      if (path[i + 1].match(/^\d+$/)) {
        ret[path[i]] = []
      } else {
        ret[path[i]] = {}
      }
    }
    ret = ret[path[i]]
  }
  ret[path[i]] = decodeURIComponent(value)
  // console.log(ret)
}

测试用例

console.log(parse('a=1&b=2&c=3')) // => { a: '1', b: '2', c: '3' }
console.log(parse('a&b&c')) // => {}
console.log(parse('a[name][second]=careteen&a[company]=sohu&b=y')) // => { a: { name: { second: 'careteen' }, company: 'sohu' }, b: 'y' }
console.log(parse('color=Deep%20Blue')) // => { color: 'Deep Blue' }
console.log(parse('a[0]=1&a[1]=2')) // => { a: [ '1', '2' ] }

总结

解析字符串看似简单,实则考察诸多知识点

  • 使用reduce去简化流程
  • 考虑URL规则满足各种需求
  • 检验对正则的掌握
  • 深层级对象的设置需要使用循环去合理设置
  • 区分数组和对象两种场景
  • 别忘了解码
@careteenL careteenL changed the title 【算法】解析URL字符串 解析URL字符串 Apr 17, 2020
@careteenL careteenL added the 算法&数据结构 算法&数据结构 label Apr 17, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
算法&数据结构 算法&数据结构
Projects
None yet
Development

No branches or pull requests

1 participant