1.常规数组扁平化
多维数组:
let arr = [
[1, 2, 2],
[3, 4, 5, 5],
[6, 7, 8, 9, [11, 12, [12, 13, [14]]]],
10
];
方案1:基于ES10中新增的flat实现扁平化处理
let flatArr = arr.flat(Infinity);
console.log(flatArr);
方案2:基于concat方式进行逐级降维
while (
arr.some(function (item) {
return Array.isArray(item);
})
) {
// arr = [].concat(...arr);
arr = [].concat.apply([], arr);
}
console.log(arr);
方案3:执行toString变为字符串的时候就已经扁平化了「不适合某一项是对象,因为对象会变为“[object Object]”」
arr = arr.toString().split(',').map(function (item) {
return +item;
});
console.log(arr);
方案4:基于递归实现
Object.defineProperty(Array.prototype, 'myFlat', {
writable: true,
configurable: true,
enumerable: false,
value: function myFlat() {
var result = [];
var next = function next(arr) {
arr.forEach(function (item) {
if (Array.isArray(item)) {
next(item);
return;
}
result.push(item);
});
};
next(this);
return result;
}
});
var flatArr = arr.myFlat();
console.log(flatArr);
2.特殊数组扁平化
let address = [{
"code": "11",
"name": "北京市",
"children": [{
"code": "1101",
"name": "市辖区",
"children": [{
"code": "110101",
"name": "东城区"
}, {
"code": "110102",
"name": "西城区"
}]
}]
}, {
"code": "13",
"name": "河北省",
"children": [{
"code": "1301",
"name": "石家庄市",
"children": [{
"code": "130102",
"name": "长安区"
}, {
"code": "130104",
"name": "桥西区"
}]
}, {
"code": "1302",
"name": "唐山市",
"children": [{
"code": "130202",
"name": "路南区"
}, {
"code": "130203",
"name": "路北区"
}]
}]
}];
方案1:递归查找「深度优先原则」
const getNameByCode = function getNameByCode(address, code) {
let result = "";
const next = arr => {
for (let i = 0; i < arr.length; i++) {
let { code: codeItor, name, children } = arr[i];
if (codeItor == code) {
result = name;
break;
}
if (Array.isArray(children)) next(children);
}
};
next(address);
return result;
}
console.log(getNameByCode(address, '130102')); //"长安区"
console.log(getNameByCode(address, '1302')); //"唐山市"
先把数组扁平化,后期查找的时候按照扁平化的数组查找即可
const getNameByCode = (function (address) {
// 先扁平化处理「广度优先原则」
let result = [];
const next = arr => {
// 先把本级处理好
let temp = arr.map(item => {
return {
code: item.code,
name: item.name
};
});
result = result.concat(temp);
// 再看是否有children,如果存在,再处理下一级
arr.forEach(item => {
if (item.children) next(item.children);
});
};
next(address);
// 返回按照code查找的方法「去扁平化后的数组中查找」
return function getNameByCode(code) {
let item = result.find(item => item.code == code);
return item ? item.name : '';
};
})(address);
console.log(getNameByCode('130102')); //"长安区"
console.log(getNameByCode('1302')); //"唐山市"
3.对象扁平化处理
/* 把对象处理为下述扁平化的结构 */
const obj = {
a: {
b: 1,
c: 2,
d: { e: 3, 2: 200 },
},
b: [1, 2, { a: 3, b: 4 }],
c: 1,
1: 100,
x: {}
};
Object.defineProperty(Object, 'flatten', {
enumerable: false,
writable: true,
configurable: true,
value: function flatten(obj) {
let result = {};
const next = (obj, attr) => {
let isObject = _.isPlainObject(obj),
isArray = Array.isArray(obj);
if (isArray || isObject) {
// 考虑为空的情况
if (isObject && _.isEmptyObject(obj)) {
result[attr] = {};
return;
}
if (isArray && obj.length === 0) {
result[attr] = [];
return;
}
// 不为空的情况则迭代处理
_.each(obj, (value, key) => {
let temp = isNaN(key) ? `.${key}` : `[${key}]`;
next(value, attr ? attr + temp : key);
});
return;
}
result[attr] = obj;
};
next(obj, "");
return result;
}
});
console.log(Object.flatten(obj));
/*
// 输出结果:
let objFlatten = {
1: 100,
'a.b': 1,
'a.c': 2,
'a.d.e': 3,
'a.d[2]': 200,
'b[0]': 1,
'b[1]': 2,
'b[2].a': 3,
'b[2].b': 4,
'c': 1,
x: {}
};
*/
4.对象扁平化处理
let obj = {
a: {
b: {
c: {
d: 1
}
}
}
};
const getValue = (obj, keyPath) => {
let keys = keyPath.split('.'),
index = 0,
result;
const next = x => {
if (index >= keys.length) return;
let key = keys[index++];
result = x[key];
if (result == null || typeof result !== "object") return;
next(result);
};
next(obj);
return result;
};
/* const getValue = (obj, keyPath) => {
let keys = keyPath.split('.');
return keys.reduce((x, key) => {
return x ? x[key] : undefined;
}, obj);
}; */
console.log(getValue(obj, 'a.b.c.d')); //1
console.log(getValue(obj, 'a.b')); //{c:{d:1}}
console.log(getValue(obj, 'a.b.x.y')); //undefined
/* 可选链处理 */
/* const getValue = (objName, keyPath) => {
keyPath = keyPath.replace(/\./g, '?.');
return eval(`${objName}?.${keyPath}`);
};
console.log(getValue('obj', 'a.b.c.d')); //1
console.log(getValue('obj', 'a.b')); //{c:{d:1}} */
5.一堆数组转树结构(一维转多维)
let data = [
{ id: 0, parentId: null, text: '北京市' },
{ id: 1, parentId: 0, text: '昌平区' },
{ id: 2, parentId: 1, text: '海淀区' },
{ id: 3, parentId: null, text: '河北省' },
{ id: 4, parentId: null, text: '山西省' },
{ id: 5, parentId: 3, text: '承德市' },
{ id: 6, parentId: 3, text: '石家庄市' }
];
/* 方案一 O(N^2) */
const list2Tree = function list2Tree(data) {
// 先找出第一级列表
let arr = data.filter(item => item.parentId === null);
// 迭代第一级的数据,筛选出其子集数据
arr.forEach(item => {
let children = data.filter(cur => cur.parentId == item.id);
if (children.length > 0) item.children = children;
});
return arr;
};
console.log(list2Tree(data));
/* 方案二:利用map数据结构处理 O(N)*/
const list2Tree = function list2Tree(data) {
// 把data变为Map数据结构
let map = new Map(),
result = [];
data.forEach(item => {
map.set(item.id, item);
});
// 迭代数组中的每一项,根据parentId做不同的处理
data.forEach(item => {
let { parentId } = item,
parent;
// parentId是null的,说明其就是第一级,我们把其加入到result中即可
if (parentId === null) {
result.push(item);
return;
}
// parentId不是null的,说明其实第二级,我们根据parentId找到其所属的第一级,把当前迭代这一项作为其children加入进去
parent = map.get(parentId);
parent.children ? parent.children.push(item) : parent.children = [item];
});
return result;
};
console.log(list2Tree(data));
6.数据组合问题
const obj = {
data: [
['xiaoming', 'male', '18', 'beijing', '2020-01-02'],
['xiaofang', 'female', '18', 'shanghai', '2020-03-02']
],
columns: [
{ name: 'name', note: '' },
{ name: 'gender', note: '' },
{ name: 'age', note: '' },
{ name: 'address', note: '' },
{ name: 'registerTime', note: '' },
]
};
输出下面结果
[
{ name: 'xiaoming', 'gender': 'male', age: '18', address: 'beijing', registerTime: '2020-01-02' },
{ name: 'xiaofang', 'gender': 'female', age: '18', address: 'shanghai', registerTime: '2020-03-02' }
]
方案一:
const combine = function combine(obj) {
let { data, columns } = obj,
columnsKeys = {};
// 先把columns变为 {name:0,gender:1,...} 这种格式
columns.forEach((item, index) => {
columnsKeys[item.name] = index;
});
// 外层迭代数据DATA
return data.map(item => {
// item: ['xiaoming', 'male', '18', 'beijing', '2020-01-02']
// columnsKeys: {name: 0, gender: 1, age: 2, address: 3, registerTime: 4}
// 想要的结果 { name: 'xiaoming', 'gender': 'male', age: '18', address: 'beijing', registerTime: '2020-01-02' }
let obj = {};
_.each(columnsKeys, (index, key) => {
obj[key] = item[index];
});
return obj;
});
};
方案二:
const combine = function combine(obj) {
let { data, columns } = obj;
// 把columns按照每列的字段名扁平化
columns = columns.map(item => item.name);
// console.log(columns); //['name', 'gender', 'age', 'address', 'registerTime']
return data.map(item => {
// item: ['xiaoming', 'male', '18', 'beijing', '2020-01-02']
// 想要的结果 { name: 'xiaoming', 'gender': 'male', age: '18', address: 'beijing', registerTime: '2020-01-02' }
let obj = {};
columns.forEach((key, index) => {
obj[key] = item[index];
});
return obj;
});
};
用qs .stringify方法转换
npm i qs
/*
const obj = {
a: {
b: 1,
c: 2,
d: { e: 3, 2: 200 },
},
b: [1, 2, { a: 3, b: 4 }],
c: 1,
1: 100,
x: {}
};
// 转换为JSON字符串
// console.log(JSON.stringify(obj));
// 转换为URLENCODED格式字符串「有的后台要求AJAX请求主体传递这样的格式」
// console.log(Qs.stringify(obj)); //'1=100&a[b]=1&a[c]=2&a[d][2]=200&a[d][e]=3&b[0]=1&b[1]=2&b[2][a]=3&b[2][b]=4&c=1'
*/