JavaScript Array、Object、数组树形结构转换、对象等数据转换及处理总结
JS 对象转数组
Object.entries()
方法返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for…in 循环遍历该对象时返回的顺序一致(区别在于 for-in 循环还会枚举原型链中的属性)。Array.prototype.map
方法创建一个新数组,其结果是该数组中的每个元素是调用一次提供的函数后的返回值。
假如说我们有一个城市的数据,这个数据记录了城市的某种值,后端一般就返回一个简单的数据格式,如:
let cityObj = {
shenzhen: 31,
guangzhou: 29
}
如果我们需要用在饼图统计图上,就需要把这个 cityObj
改成数组格式 cityArr
,如
let cityArr = [
{cityName: 'shenzhen', value: 31},
{cityName: 'guangzhou', value: 29}
]
如果属性少的话,你可以用 .
的方式手动取值赋值改成数组格式,如:
let cityArr = [
{cityName: 'shenzhen', value: cityObj.shenzhen},
{cityName: 'guangzhou', value: cityObj.guangzhou}
]
但是如果城市非常多,甚至是整个中国所有的城市,那你用 .
取值赋值的方式就会显得很麻瓜,所以这里建议用遍历的方式,或者你也可以对这个东西封装加入自己的工具函数也很好。
下面例举两种方式去完成这个对象转数组。
使用
Object.entries + Array.prototype.map
对象转数组
let cityObj = { // 对象数据
shenzhen: 31,
guangzhou: 29
}
// 封装
function objToArr(data, typeName, valueName) {
// Object.entries(data) 先把数据转成 [[key, value], ...]
// .map(([typeName, valueName]) => ({typeName, valueName})) 对 [key, value] 解构
// 然后返回 {typeName: typeName, valueName: valueName} 格式
return Object.entries(data).map(([typeName, valueName]) => ({typeName, valueName}))
}
// 执行
objToArr(cityObj, 'cityName', 'value')
使用
Object.keys + Array.prototype.map
对象转数组
let cityObj = { // 对象数据
shenzhen: 31,
guangzhou: 29
}
// 封装
function objToArr(data, typeName, valueName) {
// Object.keys(data) 先把数据转成 [key, key, key, ...]
// .map(key => ({typeName: key, valueName: data[key]}))
// 遍历 keys 取出 key 和 value data[key],
// 然后返回 {typeName: typeName, valueName: valueName} 格式
return Object.keys(data).map(key => ({typeName: key, valueName: data[key]}))
}
objToArr(cityObj, 'cityName', 'value')
JS 数组转对象
Object.fromEntries
方法把键值对列表转换为一个对象。Array.prototype.map
方法创建一个新数组,其结果是该数组中的每个元素是调用一次提供的函数后的返回值。
如果我们需要将在饼图统计图上的数据 cityArr
传给后端,一般来说都会简化数据,简化成 cityObj
,如:
let cityArr = [
{cityName: 'shenzhen', value: 31},
{cityName: 'guangzhou', value: 29}
]
let cityObj = {
shenzhen: 31,
guangzhou: 29
}
既然有 Object.entries
,也有 Object.fromEntries
,那可以直接使用 Object.fromEntries + Array.prototype.map
来完成这个格式转化
使用 Object.fromEntries + Array.prototype.map
数组转对象
let cityArr = [ // 数组数据
{ cityName: 'shenzhen', value: 31 },
{ cityName: 'guangzhou', value: 29 }
]
// 封装
function arrToObj(data, typeName, valueName) {
// data.map(item => ([item.typeName, item.valueName])) 先把数据转成 [[key, value], ...]
// Object.fromEntries() 相当于 Object.entries() 逆方法
// 然后返回 {typeName: valueName} 格式
return Object.fromEntries(data.map(item => ([item[typeName], item[valueName]])))
}
arrToObj(cityArr, 'cityName', 'value')
JS 一维数组转、树形结构数组相互转换
如果有用到权限树或者文件模块,一般都少不了从后端拿回来的数据做一维数组转树形结构,或者传输给后端时需要树形结构转一位数组扁平化,除非你和后端有亲密关系,不然的话这些都是需要前端自己来做处理。
例如,我们需要将 dataArr
转成 dataTree
let dataArr = [
{ id: 1, pid: 0 },
{ id: 2, pid: 1 }
]
let dataTree = [
{
id: 1,
pid: 0,
children: [
{
id: 2,
pid: 1
children: []
}
]
}
]
递归方法转树形结构数据
- 计算量大
- 不会改变原有数据
let data = [ // 如果后端跟你没有亲密关系,你拿到的数据就是列表
{ id: 1, pid: 0 },
{ id: 2, pid: 0 },
{ id: 3, pid: 1 },
{ id: 4, pid: 2 },
{ id: 5, pid: 3 },
{ id: 6, pid: 4 },
{ id: 7, pid: 5 },
{ id: 8, pid: 6 },
]
function arrToTreeData(data, pidVal = 0, pidName = 'pid', childName = 'children') {
// 一般 pid 就是 parentId,指的是父级 id,这里默认是 pid
// 一般 pidVal 的值为 0 时,默认是根节点
// childName 在大多数表格,多级嵌套等组件里通常都是用 children 命名,这里默认是 children
let result = [] // 初始化
// 递归匹配,计算量较大
data.forEach(item => {
if (item[pidName] === pidVal) {
result.push({
...item,
[childName]: arrToTreeData(data, item.id)
})
}
})
return result
}
arrToTreeData(data)
对象引用法转树形结构数据
- 计算量小
- 不使用深拷贝则会改变原始数据
let data = [ // 如果后端跟你没有亲密关系,你拿到的数据就是列表
{ id: 1, pid: 0 },
{ id: 2, pid: 0 },
{ id: 3, pid: 1 },
{ id: 4, pid: 2 },
{ id: 5, pid: 3 },
{ id: 6, pid: 4 },
{ id: 7, pid: 5 },
{ id: 8, pid: 6 },
]
function arrToTreeData(data, pidName = 'pid', childName = 'children') {
// 一般 pid 就是 parentId,指的是父级 id,这里默认是 pid
// childName 在大多数表格,多级嵌套等组件里通常都是用 children 命名,这里默认是 children
let obj = {} // 初始化
let result = [] // 初始化
// 将数据以对象的格式先存起来
data.forEach(item => {
obj[item.id] = item
})
for (let i = 0; i < data.length; i++) {
let item = data[i]
// 这里去 obj 里找,如果没有找到那就是 undefined,说明这个当前 item 是根节点
let parent = obj[item[pidName]]
if (parent) {
(parent[childName] || (parent[childName] = [])).push(item)
} else {
result.push(item)
}
}
return result
}
arrToTreeData(data)
广度法树形结构数据扁平化
- 不使用深拷贝则会改变原始数据
function cutTree(data, childName = 'children') {
let result = [];
while (data.length != 0) {
let shift = data.shift();
let children = shift[childName]
delete shift[childName]
result.push(shift)
if (children) {
children.forEach(item => {
data.push(item)
})
}
}
return result
}
欢迎指导交流