如何在不使用递归和json方法的情况下深度复制对象

问题描述 投票:0回答:1

如何在不使用递归、JSON.parse \ JSON.stringify、structuralClone()的情况下实现深拷贝。一个对象中可以有任意数量的元素。

 const data1 = {
  a: 10,
  y: null,
  k: [1, 2],
  b: 3,
  c: {
    d: 4,
    e: {
      w: 50,
      u: undefined,
      s: {
        f: {
          v: 5,
        },
      },
    },
  },
};

const data2 = [
{
  a: 10,
  y: null,
  k: [1, 2],
  b: 3,
  c: {
    d: 4,
    e: {
      w: 50,
      u: undefined,
      s: {
        f: {
          v: 5,
        },
      },
    },
  },
};
];

在我的示例中,我无法实现深层复制,我只是在第二个循环处停止。我们怎样才能避免递归和其他现成的解决方案?

function deepCopy(dataType) {
  const copy = {};
  let data = dataType;

  if (Array.isArray(data)) {
    data = dataType[0];
  }

  for (const [key, value] of Object.entries(data)) {
    if (typeof data[key] === "object") {
      copy[key] = Array.isArray(data[key]) ? [] : value;
      for (let deepKey in data[key]) {
        copy[key][deepKey] = data[key][deepKey];
      }
    } else {
      copy[key] = data[key];
    }
  }
  return copy;
}
javascript algorithm for-loop object
1个回答
0
投票

如果使用堆栈和引用查找图,则可以迭代该结构而无需任何递归。

这是一个细分:

  1. 判断传入的对象是否是对象,如果不是则立即返回

  2. 创建一个堆栈,其中源作为对象,目标与对象类型相同

  3. 此外,创建一个引用映射,将原始对象引用映射到目标副本

  4. 当堆栈不为空时:

    1. 从堆栈中删除项目

    2. 循环对象中的所有键(或数组索引):

      1. 如果该值是一个对象:

        1. 获取参考或创建新参考
        2. 指定参考人
        3. 将新的源/目标推入堆栈
      2. 否则,分配值

const data1 = {
  a: 10,
  y: null,
  k: [1, 2],
  b: 3,
  c: {
    d: 4,
    e: {
      w: 50,
      u: undefined,
      s: { f: { v: 5 } }
    }
  }
};
const data2 = deepCopy(data1);

// Objects are not the same reference
console.log(data1.c !== data2.c); // true
console.log(data1.c.e !== data2.c.e); // true
console.log(data1.c.e.s.f !== data2.c.e.s.f); // true

console.log(data2); // Print the copy

function deepCopy(dataType) {
  const isObject = (value) => typeof value === 'object' && value !== null;
  const targetFrom = (source) => Array.isArray(source) ? [] : {};
  if (!isObject(dataType)) { return dataType; }
  const stack = [{ source: dataType, target: targetFrom(dataType) }];
  const refMap = new Map([[dataType, stack[0].target]]);
  while (stack.length) {
    const { source, target } = stack.pop();
    for (const key in source) {
      if (source.hasOwnProperty(key)) {
        const value = source[key];
        if (isObject(value)) {
          if (!refMap.has(value)) {
            const newTarget = targetFrom(value);
            refMap.set(value, newTarget);
            stack.push({ source: value, target: newTarget });
          }
          target[key] = refMap.get(value);
        } else {
          target[key] = value;
        }
      }
    }
  }
  return refMap.get(dataType);
}
.as-console-wrapper { top: 0; max-height: 100% !important; }

© www.soinside.com 2019 - 2024. All rights reserved.