向其中包含数组的深层嵌套对象添加值

时间:2019-09-03 17:19:58

标签: javascript ecmascript-6

考虑对象:

{
  "status": {
    "affects": {
      "date_of_death": "date_of_death",
      "cause_of_death": {
        "affects": {
          "other_cause_of_death": "other_cause_of_death"
        },
        "value": "Other"
      }
    },
    "value": "Deceased"
  }
}

我想做的是对此进行循环并添加{hide: true}。但是有一些规则:

  • 如果键没有对象作为值,请将该值放入{hide: true}
  • 如果它有affects(如死因一样),则在值后面加上hide: true

因此生成的对象应该是:

{
  "status": {
    "affects": {
      "date_of_death": {hide: true},
      "cause_of_death": {
        "affects": {
          "other_cause_of_death": {hide: true}
        },
        "value": "Other",
        "hide": true,
      }
    },
    "value": "Deceased"
  }
}

现在,这看起来似乎很容易,直到您得到如下信息:

{
  "comorbidities": [
    {
      "affects": {
        "malignancy_type": {
          "affects": {
            "malignancy_type_other": "malignancy_type_other"
          },
          "value": "Other"
        }
      },
      "value": "malignancy"
    },
    {
      "affects": {
        "heritable_syndrome_type": "heritable_syndrome_type"
      },
      "value": "heritable syndrome"
    }
  ]
}

完全相同的事情应该在这里发生。接受注意它是如何排列的,这应该递归地进行,深入探究影响,直到找不到更多为止。

我已经走了这么远:

export const createHiddenFields = (dependencies) => {
  let hiddenFields = {};

  if (dependencies === null) {
    return hiddenFields;
  }

  for (const key in dependencies) {
    if (dependencies[key].hasOwnProperty('affects')) {
      hiddenFields[key] =
    } else {

    }
  }

  return hiddenFields;
}

但是我不知道该如何完成。我知道我希望它是递归的,但我也想要它快速但仍然清晰易读。

有任何想法吗?

3 个答案:

答案 0 :(得分:1)

您可能正在寻找类似的东西

export function createHiddenFields(dependencies) {
  if (Array.isArray(dependencies)) {
    return dependencies.map(createHiddenFields);
  }
  const hiddenFields = {
    hide: true,
  };
  if (typeof dependencies == 'object' && dependencies !== null) {
    for (const key in dependencies) {
      if (key == 'affects') {
        hiddenFields.affects = createHiddenFields(dependencies.affects);
      } else {
        hiddenFields[key] = dependencies[key];
      }
    }
  }
  return hiddenFields;
}

答案 1 :(得分:0)

您可以使用递归和for...in循环来执行此操作,并检查该属性的值是否为object,然后再次调用该函数,如果不是,则添加该值。

const data = {"comorbidities":[{"affects":{"malignancy_type":{"affects":{"malignancy_type_other":"malignancy_type_other"},"value":"Other"}},"value":"malignancy"},{"affects":{"heritable_syndrome_type":"heritable_syndrome_type"},"value":"heritable syndrome"}]}

function update(obj, val) {
  for (let i in obj) {
    if (typeof obj[i] == 'object') update(obj[i], val);
    else if ('affects' in obj) Object.assign(obj, val);
    else obj[i] = val
  }
}

update(data, {hide: true});
console.log(data)

答案 2 :(得分:0)

我还是决定发布一个较晚的答案,因为在其他答案中我发现了一些可能的缺陷和陷阱。具体来说:

  • Object.prototype是危险的,因为它可能会遍历任何可迭代的for ... in属性,而这些属性有时由于不负责任的开发人员而存在。通常,它会遍历所有属性,包括继承的属性
  • {hide: true} 不应该用于遍历数组
  • 重用hide对象可能是不明智的。如果以后您希望更改树中某些条目的function createHiddenFields(obj) { // ignore nulls if(obj == null) { return; } // For an array, just do the update for each object in array else if(obj instanceof Array) { for(const subObj of obj) { createHiddenFields(subObj); } } // For object, do the hidden field thing else if(typeof obj == "object") { // Replace all string values with hiddenVal for(const valueName of Object.getOwnPropertyNames(obj)) { // Do not override value nodes if(valueName == "value") { continue; } else { // Process sub-objects if(typeof obj[valueName] == "object") { createHiddenFields(obj[valueName]); } // Replace primitive property values else { obj[valueName] = { hide: true }; } } } // add hidden field for affects if(typeof obj.affects == "object") { obj.hide = true; } } } 属性,则会影响共享同一对象引用的所有对象

所以我改写一个更长但更安全的方法:

{{1}}

demo