首页 > 解决方案 > 使用 lodash 或其他 lib 引用其他属性的 Javascript 递归转换对象

问题描述

我想转换通过其属性相互引用的javascript对象,

说我有这个对象

{
  apple: {
    banana: [1,2,3],
    cherry: [4,5,6],
  },
  banana: {
    date: [7],
    cherry: [8,9],
    elderberry: [10, 11],
  },
  cherry: {
   date: [7],
   fig:  [12,13],
  },
  date: {
    fig: [11,14],
  },
},

我想把那个对象变成这个

{
  apple: {
    banana: [1,2,3],
    cherry: [4,5,6, 8,9],
    date: [7],
    elderberry: [10, 11],
    fig: [11,14, 12,13],
  },
  banana: {
    cherry: [8,9],
    elderberry: [10, 11],
    fig: [11,14, 12,13],
    date: [7],
  },
  cherry: {
    date: [7],
    fig: [11,14, 12,13],
  },
  date: {
    fig: [11,14],
  },
}

在那个例子中,苹果的樱桃属性有 [4,5,6,8,9],[4,5,6] 来自苹果,[8, 9] 来自香蕉,因为苹果引用了香蕉和香蕉有参考樱桃,因此它将被合并到[4,5,6,8,9]

而且最终的数组实际上是唯一的值

所以想法是它会递归合并其他组件值,使用 lodash 或其他库是可以的~

标签: javascriptarraysobject

解决方案


我将首先创建一个存储相反关系的结构,即从孩子到父母。

然后对于每个键/数组对,沿着路径(通过新结构)向上到达其祖先,并将数组添加到那里的相同键中。我为此选择了使用显式堆栈变量的遍历,但它与递归 DFS 遍历一样好。

最后再次访问所有数组以删除重复项。

function complete(data) {
    // Create child-parent relationships:
    const parents = {};
    for (const parent in data) {
        for (const child in data[parent]) {
            (parents[child] = parents[child] || []).push(parent);
        }
    }
    // Tree traveral to copy child array into same key in ancestors
    const result = {};
    for (const parent in data) {
        for (const child in data[parent]) {
            const arr = data[parent][child];
            const visited = new Set;
            const stack = [parent];
            while (stack.length) {
                const node = stack.pop();
                if (visited.has(node)) continue;
                visited.add(node);
                ((result[node] = result[node] || {})[child] = result[node][child] || []).push(...arr);
                stack.push(...parents[node] || []);
            }
        }
    }
    // Remove duplicate values from the arrays
    for (const parent in result) {
        for (const child in result[parent]) {
            result[parent][child] = [...new Set(result[parent][child])];
        }
    }
    return result;
}

// Example call with data from the question:
const data = {apple: {banana: [1,2,3],cherry: [4,5,6],},banana: {date: [7],cherry: [8,9],elderberry: [10, 11],},cherry: {date: [7],fig:  [12,13],},date: {fig: [11,14],},};
const result = complete(data);
console.log(result);


推荐阅读