【问题标题】:Deep copy object with Depth-First Search深度优先搜索的深拷贝对象
【发布时间】:2020-12-28 08:21:41
【问题描述】:

我试图复制一个对象。我想用算法深度优先搜索。

function dfs(data) {
  let stack = [];
  let res = {};

  for (let key in data) {
    stack.push({ data: data[key], keyData: key });

    while (stack.length !== 0) {
      const first = stack.shift();

      if (typeof first.data === "object") {
        for (let key in first.data) {
          if (typeof first.data[key] === "object") {
            stack.push({ data: first.data[key], keyData: key });
          } else {
            res[first.parentKey] = first.keyData;
          }
        }
      } else {
        res[first.keyData] = first.data;
      }
    }
  }

  return res;
}

const data = {
  a: 1,
  b: 2,
  c: {
    d: 3,
    g: {
      e: 4,
      r: {
        y: 5,
      },
    },
  },
};

const newData = dfs(data);

data.c.g.e = 5000;
data.c.g.d = 90000;

console.log("Original data", data);
console.log("Copied data", newData);

我创建了一个函数,它将复制我的对象,而不使用旧对象上的链接。我有一个问题,我的函数没有正确计算结果。我在哪里犯错了?

【问题讨论】:

    标签: javascript depth-first-search deep-copy


    【解决方案1】:

    深度优先搜索通常使用recursion

    function dfs(data) {
      if (typeof data === 'object') {
        const result = {};
        
        for (let key in data) {
          result[key] = dfs(data[key]);
        }
        
        return result;
      }
      
      return data;
    }
    
    const data = {
      a: 1,
      b: 2,
      c: {
        d: 3,
        g: {
          e: 4,
          r: {
            y: 5,
          },
        },
      },
    };
    
    const newData = dfs(data);
    
    data.c.g.e = 5000;
    data.c.g.d = 90000;
    
    console.log("Original data", data);
    console.log("Copied data", newData);

    这是一种迭代方法:

    function dfs(data) {
      const result = {};
      const source = [['ROOT', data]];
      const target = [result];
      
      while (source.length) {
        const [k, v] = source.shift();
        const current = target.shift();
        const branch = typeof v === 'object';
        
        current[k] = branch ? {} : v;
        
        if (branch) {
          const entries = Object.entries(v);
          source.unshift(...entries);
          target.unshift(...Array(entries.length).fill(current[k]));
        }
      }
      
      return result.ROOT;
    }
    
    const data = {
      a: 1,
      b: 2,
      c: {
        d: 3,
        g: {
          e: 4,
          r: {
            y: 5,
          },
        },
      },
    };
    const newData = dfs(data);
    
    data.c.g.e = 5000;
    data.c.g.d = 90000;
    
    console.log("Original data", data);
    console.log("Copied data", newData);

    【讨论】:

    • 如何在没有递归的情况下创建它?有可能吗?
    • 因为我只需递归即可。
    【解决方案2】:

    没有递归的 dfs 使用额外的堆栈来跟踪父属性。

        function dfs(data) {
            let stack = [];
            let stackres = [];
            let res = {};
        
            for (let key in data) {
                stack.push({ data: data[key], keyData: key });
                stackres.push(res);
        
        
                while (stack.length !== 0) {
                    const first = stack.shift();
                    const cur = stackres.shift();
        
                    if (typeof first.data === "object") {
                        cur[first.keyData] = {};
                        for (let key in first.data) {
                            if (typeof first.data[key] === "object") {
                                stack.push({ data: first.data[key], keyData: key });
                                stackres.push(cur[first.keyData]);
                            } else {
                                cur[first.keyData][key] = first.data[key];
                            }
                        }
                    } else {
                        cur[first.keyData] = first.data;
                    }
                }
            }
        
            return res;
        }
        const data = {
          a: 1,
          b: 2,
          c: {
            d: 3,
            g: {
              e: 4,
              r: {
                y: 5,
              },
            },
          },
        };
        const newData = dfs(data);
        
        data.c.g.e = 5000;
        data.c.g.d = 90000;
        
        console.log("Original data", data);
        console.log("Copied data", newData);

    【讨论】:

    • 我明白了。我没有堆栈来跟踪父属性。
    猜你喜欢
    • 1970-01-01
    • 2015-09-14
    • 1970-01-01
    • 1970-01-01
    • 2011-01-31
    • 1970-01-01
    • 2012-06-19
    相关资源
    最近更新 更多