将对象的平面数组转换为不同深度的嵌套对象[重复]

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

我有一个对象数组:

const flatData = [
  {
    "name": "Fish 1",
    "price": 15
  },
  {
    "name": "Super Fish 1",
    "price": 12,
    "family": "Super Fish family"
  },
  {
    "name": "Super Fish 2",
    "price": 17,
    "family": "Super Fish family"
  },
  {
    "name": "Super Fish 3",
    "price": 16,
    "family": "Super Fish family"
  },
  {
    "name": "Awful legged Fish 1",
    "price": 22,
    "family": "Awful Fish family",
    "sub_family": "Awful Fish with legs"
  },
  {
    "name": "Awful legged Fish 2",
    "price": 15,
    "family": "Awful Fish family",
    "sub_family": "Awful Fish with legs"
  },
  {
    "name": "Awful legged Fish 3",
    "price": 23,
    "family": "Awful Fish family",
    "sub_family": "Awful Fish with legs"
  },
  {
    "name": "Awful blue dotted Fish 1",
    "price": 10,
    "family": "Awful Fish family",
    "sub_family": "Awful Fish with blue dots"
  },
  {
    "name": "Awful blue dotted Fish 2",
    "price": 11,
    "family": "Awful Fish family",
    "sub_family": "Awful Fish with blue dots"
  }
]

我想将其转换为嵌套的对象数组:

const nestedData = [
  {
    "id": "0",
    "name": "Fish 1",
    "price": 15
  },
  {
    "id": "1",
    "name": "Super Fish family",
    "selected": -1,
    "family": [
      {
        "id": "0",
        "name": "Super Fish 1",
        "price": 12
      },
      {
        "id": "1",
        "name": "Super Fish 2",
        "price": 17
      },
      {
        "id": "2",
        "name": "Super Fish 3",
        "price": 16
      }
    ]
  },
  {
    "id": "2",
    "name": "Awful Fish family",
    "selected": -1,
    "family": [
      {
        "id": "0",
        "name": "Awful Fish with legs",
        "selected": -1,
        "family": [
          {
            "id": "0",
            "name": "Awful legged Fish 1",
            "price": 22
          },
          {
            "id": "1",
            "name": "Awful legged Fish 2",
            "price": 15
          },
          {
            "id": "2",
            "name": "Awful legged Fish 3",
            "price": 23
          }
        ]
      },
      {
        "id": "1",
        "name": "Awful Fish with blue dots",
        "selected": -1,
        "family": [
          {
            "id": "0",
            "name": "Awful blue dotted Fish 1",
            "price": 10
          },
          {
            "id": "1",
            "name": "Awful blue dotted Fish 2",
            "price": 11
          }
        ]
      }
    ]
  }
]

我以为我可以将问题分解为一系列不太复杂的问题,但我被困在这一步了。我找到了基于拆分字符串的解决方案,但我的平面文件不同。 “family”和“sub_family”的存在,我可以从一个值推断出深度信息......

有没有一个js库可以让这变得更容易?

javascript arrays multidimensional-array nested javascript-objects
1个回答
0
投票

嗯,基于类似的答案,我或多或少添加了一些属性来适应相同的解决方案。

const flatData = [{
    "name": "Fish 1",
    "price": 15
  },
  {
    "name": "Super Fish 1",
    "price": 12,
    "family": "Super Fish family"
  },
  {
    "name": "Super Fish 2",
    "price": 17,
    "family": "Super Fish family"
  },
  {
    "name": "Super Fish 3",
    "price": 16,
    "family": "Super Fish family"
  },
  {
    "name": "Awful legged Fish 1",
    "price": 22,
    "family": "Awful Fish family",
    "sub_family": "Awful Fish with legs"
  },
  {
    "name": "Awful legged Fish 2",
    "price": 15,
    "family": "Awful Fish family",
    "sub_family": "Awful Fish with legs"
  },
  {
    "name": "Awful legged Fish 3",
    "price": 23,
    "family": "Awful Fish family",
    "sub_family": "Awful Fish with legs"
  },
  {
    "name": "Awful blue dotted Fish 1",
    "price": 10,
    "family": "Awful Fish family",
    "sub_family": "Awful Fish with blue dots"
  },
  {
    "name": "Awful blue dotted Fish 2",
    "price": 11,
    "family": "Awful Fish family",
    "sub_family": "Awful Fish with blue dots"
  }
]



function unflatten(arr) {
  var tree = []

  // create helper property of ancestry as array
  arr.map(function(item) {
    item.idPathOfEntityToAttribute = []
    item.family && item.idPathOfEntityToAttribute.push(item.family)
    item.sub_family && item.idPathOfEntityToAttribute.push(item.sub_family)
    item.idPathOfEntityToAttribute.push(item.name)
    delete item.family
    delete item.sub_family
    return item
  })

  // group by name for easy access
  var grouped = arr.reduce(function(agg, item) {
    agg[item.name] = item
    item.selected = -1
    item.family = []

    // make sure item path exists
    var path = [...item.idPathOfEntityToAttribute]
    var so_far = []
    while (path.length) {
      var parent = path.shift()
      so_far.push(parent)
      if (!agg[parent]) {
        agg[parent] = {
          name: parent,
          selected: -1,
          family: [],
          idPathOfEntityToAttribute: [...so_far]
        }
      }
    }

    return agg;
  }, {})


  Object.keys(grouped).forEach(function(key) {
    var item = grouped[key];

    // attach to the tree or to the parent
    var len = item.idPathOfEntityToAttribute.length
    var parent_id = len > 1 ? item.idPathOfEntityToAttribute[len - 2] : null
    if (parent_id) {
      var parent = grouped[parent_id]
      parent.family.push(item);
    } else {
      tree.push(item)
    }
  })

  // optionally clean by removing idPathOfEntityToAttribute
  Object.keys(grouped).forEach(function(key) {
    var item = grouped[key];
    if (!item.family.length) {
      delete item.family
      delete item.selected
    }
    delete item.idPathOfEntityToAttribute
  })

  // adding index property
  add_indexes(tree)

  return tree;
}


function add_indexes(tree) {
  for (var i = 0; i < tree.length; i++) {
    var item = tree[i]
    tree[i] = {
      id: "" + i,
      ...item
    }
    if (item.family) {
      add_indexes(item.family)
    }
  }
}

var tree = unflatten(flatData)

console.log(tree)
.as-console-wrapper {
  max-height: 100% !important;
  min-height: 100% !important;
}

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