求大佬们优化一下代码,屎山代码给孩子头皮想破了

2021-06-18 15:57:53 +08:00
 happyCodings
秉着不写垃圾代码的原则,求大佬优化一下,最优值奉上红包
需求是这样的:

万恶后端传过来的数据:
"data":[{"province":"上海市","city":"上海市市辖区","adcode":"310118","district":"青浦区"},
{"province":"江苏","city":"苏州市","adcode":"320506","district":"吴中区"},
{"province":"山西省","city":"阳泉市","adcode":"140302","district":"城区"},
{"province":"上海市","city":"上海市市辖区","adcode":"310101","district":"黄浦区"},
{"province":"河北省","city":"石家庄市","adcode":"130123","district":"正定县"}]

需要整合成这样 elementUi 中级联选择器中的数据:
(只要有相同的就要去重并在之前的 children 下加入重复的 children )
addressOptions: [
{
value: "zhinan",
label: "指南",
children: [
{
value: "shejiyuanze",
label: "设计原则",
children: [
{
value: "yizhi",
label: "一致",
},
{
value: "fankui",
label: "反馈",
},
{
value: "xiaolv",
label: "效率",
},
{
value: "kekong",
label: "可控",
},
],
},
{
value: "daohang",
label: "导航",
children: [
{
value: "cexiangdaohang",
label: "侧向导航",
},
{
value: "dingbudaohang",
label: "顶部导航",
},
],
},
],
},
],

我的垃圾代码:

dealWithAddressList(arr, name) {
var city = {};
return arr.reduce(function (item, ele) {
console.log(ele[name]);
if (city[ele[name]]) {
item.forEach((eles) => {
if (eles.label == ele[name]) {
eles.children.forEach((eless) => {
if (eless.value == ele.city) {
eless.children.push({
value: ele.adcode,
label: ele.district,
});
} else {
eles.children.push({
value: ele.city,
label: ele.city,
children: [
{
value: ele.adcode,
label: ele.district,
},
],
});
}
});
}
});
console.log(city[ele[name]]);
} else {
city[ele[name]] =
true &&
item.push({
value: ele.province,
label: ele.province,
children: [
{
value: ele.city,
label: ele.city,
children: [
{
value: ele.adcode,
label: ele.district,
},
],
},
],
});
}
console.log(item);
return item;
}, []);
},

求大佬优化一下,可以的话有红包奉上
7879 次点击
所在节点    Vue.js
60 条回复
yiqiao
2021-06-18 16:00:10 +08:00
为什么不直接让后端改下?
happyCodings
2021-06-18 16:05:32 +08:00
@yiqiao 后端傻瓜不改 想锤他
meshell
2021-06-18 16:15:21 +08:00
@happyCodings 我觉得这个确实不要后端改,前端自已转换所需要的结构
AidenChen
2021-06-18 16:21:59 +08:00
这个就是要前端改,后端始终提供列表以适应不同的展示需求;这里的处理实质上就是以根节点为最终父级,生成子孙树
jenlors
2021-06-18 16:23:28 +08:00
后端没毛病
xiangyuecn
2021-06-18 16:28:08 +08:00
后端给平铺展开的数据(一层数组),数据库里面怎么存的就怎么拿,没毛病

结构格式化,js 很容易(简洁),大部分后端语言很困难(蹩脚难看)

你这个递归几行代码就搞定了,也更容易理解,你倒好 for 也不写,reduce 有那么香吗?
TomatoYuyuko
2021-06-18 16:34:09 +08:00
这不是前端基本功嘛,生成树,面试都经常会遇到的题,自己写个工具类处理,递归几层就出来了。遇到这种问题不要硬循环,后面维护看到你人都麻了。。
TomatoYuyuko
2021-06-18 16:38:35 +08:00
前端数据处理直接用 lodash,我记得有现成的方法,你找找
liyang5945
2021-06-18 16:39:25 +08:00
你这个就两级吗,两级我有个简单的写法
a719031256
2021-06-18 16:39:32 +08:00
@happyCodings
这个不应该后端改,前几天还在给我配合的前端说这个事情
前端需求变化很快,每次变化都要后端给前端再封装数据,就不方便了,还不如后端反你固定格式数据,前端按实际需求封装自己的需要的格式
aguesuka
2021-06-18 16:39:44 +08:00
class Address {
/**
* @type string
*/
province

/**
* @type string
*/
city

/**
* @type string
*/
adcode

/**
* @type string
*/
district
}

class TreeNode {
/**
* @type string
*/
value
/**
* @type string
*/
label

/**
* @type TreeNode[]
*/
children
}

/**
*
* @param addresses {Address[]}
* @return TreeNode[]
*/
function dealWithAddressList(addresses) {
/**
* @type {TreeNode[]}
*/
const result = []
/**
*
* @type {Map<string, TreeNode>}
*/
const createdElements = new Map()
/**
*
* @param value {string}
* @param brothers {TreeNode[]}
* @returns {TreeNode}
*/
const nodeOf = (value, brothers) => {
let node = createdElements.get(value);
if (node === undefined) {
node = {
children: [],
value: value,
label: value,
}
brothers.push(node)
createdElements.set(value, node)
}
return node
}

for (let address of addresses) {
let provinceNode = nodeOf(address.province, result)
let cityNode = nodeOf(address.city, provinceNode.children);
cityNode.children.push({
children: [],
value: address.adcode,
label: address.district,
})
}
return result;
}

function test() {
return dealWithAddressList([{"province": "上海市", "city": "上海市市辖区", "adcode": "310118", "district": "青浦区"},
{"province": "江苏", "city": "苏州市", "adcode": "320506", "district": "吴中区"},
{"province": "山西省", "city": "阳泉市", "adcode": "140302", "district": "城区"},
{"province": "上海市", "city": "上海市市辖区", "adcode": "310101", "district": "黄浦区"},
{"province": "河北省", "city": "石家庄市", "adcode": "130123", "district": "正定县"}]);
}

test()
zhangchongjie
2021-06-18 16:43:54 +08:00
返回的数据结构如果也是后端改,那一个共用接口得写多少返回类型呀
ccraohng
2021-06-18 16:48:15 +08:00
function convert() {
const levels = ['province', 'city', 'district'];
const result = {
children: {},
};

data.forEach((item) => {
levels.reduce((map, level) => {
const current = item[level];

if (!map.children) {
map.children = {};
}

map.children[current] = map.children[current] || {
data: {
label: current,
value: level === 'district' ? item.adcode : current,
},
};

return map.children[current];
}, result);
});

const format = (item) => {
if (item.children) {
const children = Object.values(item.children).map((child) => {
return format(child);
});

item.children = children;
}

return item;
};

const root = format(result).children;
console.log(root);
}
convert();
Vegetable
2021-06-18 16:48:24 +08:00
http://js.jsrun.net/RQVKp

处理省市区什么的写的比较难看,大概就是这个思路吧
通过一个 hash 做映射,方便找到父节点
HashV2
2021-06-18 16:54:57 +08:00
我做后端的时候都是前端来改结构,我做前端的时候都是后端来改结构(因为我比较能喷,而且不怕 delay )

现在我全栈了,哪边简单方便哪边改。。。(现在贼怕 delay,deadline 就是第一生产力)
ryncv
2021-06-18 16:55:33 +08:00
O(1)复杂度
```javascript
const data =[{"province":"上海市","city":"上海市市辖区","adcode":"310118","district":"青浦区"},
{"province":"江苏","city":"苏州市","adcode":"320506","district":"吴中区"},
{"province":"山西省","city":"阳泉市","adcode":"140302","district":"城区"},
{"province":"上海市","city":"上海市市辖区","adcode":"310101","district":"黄浦区"},
{"province":"河北省","city":"石家庄市","adcode":"130123","district":"正定县"}];

function listToTree(list) {
const map = {};
list.forEach(({province, city, district, adcode}) => {
const item = {name: district, value: adcode};
if (!map[province]) {
map[province] = {
name: province,
children: [{
name: city,
children: [item]
}]
}
return;
}
const cityItem = map[province].children.find(one => one.name === city);
if (!cityItem) {
map[province].children.push({ name: city,children: [item]})
} else {
cityItem.children.push(item);
}
})
return Object.values(map);
}

console.log(listToTree(data));
```
bnm965321
2021-06-18 16:55:49 +08:00
看看 python 的 defaultDict,然后套两层嵌套的 defaultDict 就知道怎么做了
timedivision
2021-06-18 17:16:38 +08:00
``` js
const data = [
{
province: '上海市',
city: '上海市市辖区',
adcode: '310118',
district: '青浦区',
},
{ province: '江苏', city: '苏州市', adcode: '320506', district: '吴中区' },
{ province: '山西省', city: '阳泉市', adcode: '140302', district: '城区' },
{
province: '上海市',
city: '上海市市辖区',
adcode: '310101',
district: '黄浦区',
},
{
province: '河北省',
city: '石家庄市',
adcode: '130123',
district: '正定县',
},
];

const pObj = {};
const cObj = {};
data.forEach(item => {
const { province, city } = item;
if (pObj[province]) {
pObj[province].push(item);
} else {
pObj[province] = [item];
}
if (cObj[city]) {
cObj[city].push(item);
} else {
cObj[city] = [item];
}
});
const proValue = Object.values(pObj);
const cityKey = Object.keys(cObj);
const res = [];
proValue.forEach(pro => {
cityKey.forEach(key => {
if (pro[0] && key === pro[0].city) {
res.push({
value: pro[0].adcode,
label: pro[0].province,
children: [
{
label: key,
value: pro[0].adcode,
children: cObj[key].map(dis => {
return {
label: dis.district,
value: pro[0].adcode,
};
}),
},
],
});
}
});
});
console.log(JSON.stringify(res));
```

写的不是很好,但是应该可以满足你的需求
lumotian
2021-06-18 17:31:52 +08:00
aitaii
2021-06-18 17:38:55 +08:00
友情提示:可以使用 gist 贴代码,这样代码格式会保留。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/784284

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX