通过检查其 属性 来更新父数组:Javascript

Update the parent array by checking its property: Javascript

我有一个深度嵌套的对象数组 arr1 具有某些属性,并给定另一个数组 arr2 作为输入,需要比较其中的相应名称并获取值并追加它到阵列之一。如果名称不在 arr2 中,则设置为默认配置,即 { val1: false, val2: false, applyToChildren: false },以防其父 applyToChildren 设置为 false。如果它设置为 true,则将其父配置复制到结果中。

结构看起来像,

const arr1 = [
  {
    name: "internalcorp.com",
    children: [
      {
        name: "internalcorp.com.child1",
        children: [
          {
            name: "internalcorp.com.grandchild1",
            children: []
          }
        ]
      },
      {
        name: "internalcorp.com.child2",
        children: []
      }
    ]
  },
  {
    name: "internalcorpwebsite.com",
    children: []
  }
];

const arr2 = [
  {
    name: "internalcorp.com",
    val1: false,
    val2: false,
    applyToChildren: true
  },
  {
    name: "internalcorp.com.child1",
    val1: true,
    val2: true,
    applyToChildren: true
  },
  {
    name: "internalcorp.com.child2",
    val1: true,
    val2: false,
    applyToChildren: true
  },
  {
    name: "internalcorpwebsite.com",
    val1: false,
    val2: false,
    applyToChildren: true
  }
];

输出应该是这样的,

const output = [
  {
    name: "internalcorp.com",
    config: {
      val1: false,
      val2: false,
      applyToChildren: true
    },
    children: [
      {
        name: "internalcorp.com.child1",
        config: {
          val1: true,
          val2: true,
          applyToChildren: true
        },
        children: [
          {
            name: "internalcorp.com.grandchild1",
            children: [],
            config: {
              val1: true,
              val2: true,
              applyToChildren: true
            }
          }
        ]
      },
      {
        name: "internalcorp.com.child2",
        children: [],
        config: {
          val1: true,
          val2: false,
          applyToChildren: true
        }
      }
    ]
  },
  {
    name: "internalcorpwebsite.com",
    children: [],
    config: {
      val1: false,
      val2: false,
      applyToChildren: true
    }
  }
];

此处 internalcorp.com.grandchild2 不存在于 arr2 中,因为它的父 applyToChildrentrue,我将其配置复制到结果

我试过的代码

const addConfig = (items) =>
  items.map(item => {
    const { val1, val2, applyToChildren } = arr2.find(p => p.name === item.name);
    return {
      ...item,
      config: {
        val1,
        val2,
        applyToChildren
      },
      children: addConfig(item.children)
    };
  });

const result = addConfig(arr1);

你可以用一个简单的 Array.forEach

逻辑。

  • 遍历arr1
  • 中的每个对象
  • 检查 arr1 中的每个对象,如果 arr2 中存在具有相同 name 的值。
  • 如果存在更新该节点的 config
  • 如果没有,请检查其父项是否设置了 applyToChildren
  • 如果设置使用父级的配置
  • 否则使用默认配置
  • 我已经使用JSON.parse(JSON.stringify(arr1))作为参数,以确保执行深拷贝

沃林Fiddle

const arr1 = [{name: "internalcorp.com", children: [{name: "internalcorp.com.child1",children: [ { name: "internalcorp.com.grandchild1", children: [] } ]},{name: "internalcorp.com.child2",children: []}]},{name: "internalcorpwebsite.com",children: []}];

const arr2 = [{ name: "internalcorp.com", val1: false, val2: false, applyToChildren: true },{ name: "internalcorp.com.child1", val1: true, val2: true, applyToChildren: true },{ name: "internalcorp.com.child2", val1: true, val2: false, applyToChildren: true },{ name: "internalcorpwebsite.com", val1: false, val2: false, applyToChildren: true }];

const defaultConfig = { val1: false, val2: false, applyToChildren: false };

const addConfig = (items, parentNode) => {
  items.forEach((node) => {
    const valueNode = arr2.find(value => value.name === node.name);
    if(valueNode) {
      const { name, ...config } = valueNode;
      node.config = config;
    } else {
      if (parentNode && parentNode.config && parentNode.config.applyToChildren) {
        node.config = parentNode.config;
      } else {
        node.config = defaultConfig;
      }
    }
    if(node.children && node.children.length > 0) {
      node.children.forEach(child => addConfig(node.children, node))
    }
  })
  return items;
}

const result = addConfig(JSON.parse(JSON.stringify(arr1)), null);
console.log(result);

以下提供的解决方案使用递归 map based approach. It in addition utilizes the so often forgotten thisArg 参数,可以作为 map 的第二个参数提供,其中 thisArg 然后作为回调的(映射函数的)this上下文。

该解决方案还将子项目 config 数组转换为一个对象,该对象用于基于项目 name 的更简单的项目特定配置查找。为了将父级特定配置更深入地传递到递归中,绑定配置数据以 {lookup, config} 形式提供,其中 lookup 包含整个配置数据,而 config 包含最多的引用最近父项目的配置。

function recursivelyAggregateChildItemFromBoundConfigData(item) {
  const { lookup, config: parentConfig } = this;
  const { name, children = [] } = item;
  const config = { ...(lookup[name] ?? parentConfig) };
  // { ...{} } decouples any direct `config` reference.
  return {
    name,
    config,
    children: children.map(
      recursivelyAggregateChildItemFromBoundConfigData,
      { lookup, config }
    ),
  };
}

const nestedData = [{
  name: "internalcorp.com",
  children: [{
    name: "internalcorp.com.child1",
    children: [{
      name: "internalcorp.com.grandchild1",
      children: [],
    }],
  }, {
    name: "internalcorp.com.child2",
    children: [],
  }],
}, {
  name: "internalcorpwebsite.com",
  children: []
}];

const itemConfigList = [{
  name: "internalcorp.com",
  val1: false,
  val2: false,
  applyToChildren: true
}, {
  name: "internalcorp.com.child1",
  val1: true,
  val2: true,
  applyToChildren: true
}, {
  name: "internalcorp.com.child2",
  val1: true,
  val2: false,
  applyToChildren: true
}, {
  name: "internalcorpwebsite.com",
  val1: false,
  val2: false,
  applyToChildren: true
}];

console.log(
  'lookup table/index/map ...',
  Object.fromEntries(
    itemConfigList.map(({ name:key, ...value }) => [key, value])
  )
);
console.log(
  'recursively mapped nested data ...',
  nestedData.map(recursivelyAggregateChildItemFromBoundConfigData, {
    lookup: Object.fromEntries(
      itemConfigList.map(({ name:key, ...value }) => [key, value])
    ),
    config: null,
  })
);
.as-console-wrapper { min-height: 100%!important; top: 0; }