【问题标题】:Nesting dot notation within bracket notation to create nested objects在括号表示法中嵌套点表示法以创建嵌套对象
【发布时间】:2020-04-05 01:45:54
【问题描述】:

“编写一个函数arrayToList,构建一个类似的列表结构”

让 LL = { data: 1, next: { data: 2, next: { data: 3, next: null }}};

我了解这个问题的典型解决方案,列表必须由内而外构建:

function arrToLList(arr) {
  let LList = null;
  for (let i = arr.length - 1; i >= 0; i--) {
    LList = { data: arr[i], next: LList };
  }
  return LList;
}

但我最初的解决方案是使用典型的 for 循环强制它。

function arrayToLList(arr) {
  let d = "data";
  let n = "next";

  let LList = nextNode();

  for (let i = 0; i < arr.length; i++) {
    LList[d] = arr[i];
    d = "next." + d;
    LList[n] = nextNode();
    n = "next." + n;
  }

  function nextNode() {
    return {
      data: null,
      next: null
    };
  }

  return LList;
}

【问题讨论】:

  • 如果您实现this question 的答案之一或使用lodash get 方法,您的解决方案就可以工作
  • 抱歉,您需要的是 lodash set 方法

标签: javascript data-structures nested javascript-objects


【解决方案1】:

您想要实现的目标是可能的,但是当您使用括号表示法时,您需要自定义获取属性的工作方式。正如您所提到的,将点符号与括号符号一起使用是行不通的,您需要一种自己定义此逻辑的方法。 ES6 引入了Proxies,它允许你为你的对象指定一个set 方法陷阱。每当您在对象上设置值时,都会调用 set 方法。使用这个想法,您可以通过. 拆分点符号字符串并遍历它返回的路径以获取嵌套对象。检索到嵌套对象后,您可以设置它的值。

请看下面的例子:

function arrayToLList(arr) {
  let d = "data";
  let n = "next";

  let LList = nextNode();

  for (let i = 0; i < arr.length; i++) {
    LList[d] = arr[i];
    d = "next." + d;
    
    if(i < arr.length-1) // don't add null object to last node
      LList[n] = nextNode();
    n = "next." + n;
  }

  function nextNode() {
    const obj = {
      data: null,
      next: null
    };
    
    return new Proxy(obj, {
      set: function(obj, key, val) {
        const path = key.split('.');
        const last = path.pop();
        for(const prop of path) 
          obj = obj[prop];
       
        obj[last] = val;
        return true;
      }
    });
  }

  return LList;
}

console.log(arrayToLList([1, 2, 3]));

但是,您不需要使用代理。一种更直接的方法是创建一个方法,例如setValueByPath(val, obj, strPath),它为您执行代理中的逻辑。然后,您只需调用setValueByPath(obj, strPath),而不是使用括号表示法设置对象:

function setValudByPath(val, obj, strPath) { // pefroms same logic from proxy, just using reduce instead
  const path = strPath.split('.');
  const last = path.pop();
  path.reduce((nested, p) => nested[p], obj)[last] = val;
}

function arrayToLList(arr) {
  let d = "data";
  let n = "next";

  let LList = {data: null, next: null};

  for (let i = 0; i < arr.length; i++) {
    setValudByPath(arr[i], LList, d); // same as LList[d] = arr[i];
    d = "next." + d;
    
    if(i < arr.length-1) // don't add null object to last node
      setValudByPath({data: null, next: null}, LList, n); // same as: LList[n] = nextNode();
    n = "next." + n;
  }

  return LList;
}

console.log(arrayToLList([1, 2, 3]));

【讨论】:

    【解决方案2】:

    当您尝试使用字符串访问对象参数时。 您不能对字符串使用点表示法。 例如

    let data = {name:'test'};
    console.log("data.name");
    

    这是您正在尝试的,它将返回 data.name 而不是值 test

    您可以执行以下操作:data['name'] 因此使用嵌套对象您可以执行以下操作:

    LList['next']['next']...['next']['data']
    

    获取第 n 个数据元素。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-06
      • 1970-01-01
      • 1970-01-01
      • 2015-09-30
      • 1970-01-01
      相关资源
      最近更新 更多