首页 > 解决方案 > JavaScript - 创建具有多级数组支持的 deepSet()

问题描述

所以我需要deepSet()在我的 React 应用程序中添加一个函数,而且我知道有几十个库可用。但是,我的要求超出了标准deepSet()。我的函数必须能够支持数组和路径中的多个数组。

示例,简单deepSet()

var obj = { one: { two: {three: 'a'}} };
deepSet(obj, 'one.two.three', 'yay');
// {one: {two: { three: 'yay' } } }

我需要它来支持(并且有工作)

var obj = { one: { two: [{three: 'a'}, {three: 'a'}] } };
deepSet(obj, 'one.two[].three', 'yay');
// { one: { two: [{three: 'yay'}, {three: 'yay'}] }};

我也需要它来支持,但还没有工作

var obj = { one: { two: [{three: [{four:'a'}, {four:'b'}]}, {three: [{four:'a'}, {four:'b'}]}]}};
deepSet(obj, 'one.two[].three[].four', 'yay');
// { one: { two: [{three: [{four:'yay'}, {four:'yay'}]}, {three: [{four:'yay'}, {four:'yay'}]}]}};

我的问题是我不知道如何获得下一级数组并迭代它们。我认为递归方法在这里是最好的,但我无法弄清楚处理 2 个或更多数组。我在这上面花了几个小时,正在向 SO 寻求帮助。

这是我到目前为止的算法,它支持 0 级和 1 级数组。

const deepSet = (object, path, value) => {
    let fields = path.split('.');
    for (let i=0; i<fields.length; i++) {
        let f = fields[i];
        if (f.indexOf("[]") > -1) {
            let arrayfield = f.replace('[]', '');
            f = fields[++i];
            object[arrayfield].forEach((el, idx) => {
                if (isEmpty(el[f])) {
                    el[f]= {};
                }
                if (i === fields.length - 1) {
                    el[f] = value;
                }
            });
            object = object[arrayfield];
        }
        else {
            if (isEmpty(object[f])) {
                object[f] = {};
            }
            if (i === fields.length - 1) {
                object[f] = value;
            }
            object = object[f];
        }
    };
}

标签: javascriptlodash

解决方案


您需要在找到这些分支时遍历分支,以便每个分支条目都变成一个新的deepSet.

例子

const deepSet = (obj, path, value) => {
  const re = /(\.|\[\]\.)/g;
  let i = 0, match = null;
  while (match = re.exec(path)) {
    const sep = match[0];
    const {length} = sep;
    const {index} = match;
    obj = obj[path.slice(i, index)];
    i = index + length;
    if (1 < length) {
      path = path.slice(i);
      obj.forEach(obj => {
        deepSet(obj, path, value);
      });
      return;
    }
  }
  obj[path.slice(i)] = value;
};

var obj = { one: { two: [{three: [{four:'a'}, {four:'b'}]}, {three: [{four:'a'}, {four:'b'}]}]}};
deepSet(obj, 'one.two[].three[].four', 'yay');

这将产生预期的结果:

{
  "one": {
    "two": [
      {
        "three": [
          {
            "four": "yay"
          },
          {
            "four": "yay"
          }
        ]
      },
      {
        "three": [
          {
            "four": "yay"
          },
          {
            "four": "yay"
          }
        ]
      }
    ]
  }
}

希望它有帮助,或者至少,它给了你一个提示


推荐阅读