【引出问题】
一个数组里有多个对象,如何根据对象某个相同属性,重新组成新数组,如下:
data= [{group: "文字", name: "DEVCODE", unit: "", value: ""},
{group: "约束", name: "与邻近图元一同移动", unit: "", value: "否"},
{group: "约束", name: "主体", unit: "", value: "标高 : 标高 1"}
];
data1= [{
"group": "约束",
infoList: [{
name: "DEVCODE",
unit: "",
value: ""
}]
},{
"group": "约束",
infoList: [{
name: "与邻近图元一同移动",
unit: "",
value: "否"
},{
name: "主体",
unit: "",
value: "标高 : 标高 1"
}]
}];
【示例代码--解答】
//一个数组里有多个对象,如何根据对象某个相同属性,重新组成新数组
function trans (data, keys) {
let cache = {};
return data.reduce((sum, cur) => {
let obj = {};
let key = keys.reduce((sum, key) => {
let tmp = obj[key] = cur[key];
delete cur[key];
return sum + tmp;
}, '');
let i = cache[key];
if (i !== undefined) {
sum[i].infoList.push(cur);
} else {
cache[key] = sum.length;
sum.push(Object.assign(obj, {infoList: [cur]}));
}
return sum;
}, []);
}
//构件详情弹框的信息展示
//1-基本属性 --bim信息
sdk.getCompBimInfo(curCompId, function (curBimInfo) {
//获取构件bim信息
console.log(curBimInfo);
$('#m_tabs_1_1').empty();
var htmlObj,htmlObj_1,htmlObj_2 = '';
htmlObj_1 = '<div class="b-portlet b-portlet--creative">
' +
' <div class="b-portlet__head">
' +
' <span class="b-portlet__title">基本信息</span>
' +
' </div>
' +
' <div class="b-portlet__body">
' +
' <div class="row-wrap-unoffset bim-info-list">
' +
' <div class="col-lg-2 col-md-2 col-sm-12 bim-info-label">名称</div>
' +
' <div class="col-lg-4 col-md-4 col-sm-12 bim-info-value">'+ curBimInfo.name +'</div>
' +
' <div class="col-lg-2 col-md-2 col-sm-12 bim-info-label">大类</div>
' +
' <div class="col-lg-4 col-md-4 col-sm-12 bim-info-value">'+ curBimInfo.dalei +'</div>
' +
' <div class="col-lg-2 col-md-2 col-sm-12 bim-info-label">小类</div>
' +
' <div class="col-lg-4 col-md-4 col-sm-12 bim-info-value">'+ curBimInfo.xiaolei +'</div>
' +
' </div>
' +
' </div>
' +
' </div>';
//处理bim数据,props数组按照group去分类展示
let propsList = trans(curBimInfo.props, ['group']); //props对象数组重新组合
console.log(propsList);
for(let j=0; j<propsList.length; j++){
let listItemWrap_b,listItemWrap_e,listItem = '';
let wrapData = propsList[j];
listItemWrap_b = '<div class="b-portlet b-portlet--creative">
' +
'<div class="b-portlet__head">
' +
'<span class="b-portlet__title">'+ wrapData.group +'</span>
' +
'</div>
' +
'<div class="b-portlet__body">
' +
'<div class="row-wrap-unoffset bim-info-list">
';
listItemWrap_e = '</div>
'+
'</div>
' +
'</div>';
for(let k=0; k<wrapData.infoList.length; k++){
let itemData = wrapData.infoList[k];
listItem +=
'<div class="col-lg-2 col-md-2 col-sm-12 bim-info-label">'+ itemData.name +'</div>
' +
'<div class="col-lg-4 col-md-4 col-sm-12 bim-info-value">'+ itemData.value + itemData.unit +'</div>
';
}
htmlObj_2 += listItemWrap_b + listItem + listItemWrap_e;
}
htmlObj = htmlObj_1 + htmlObj_2;
$('#m_tabs_1_1').html(htmlObj);
});
【知识学习】
1、JS数组reduce方法
reduce() 方法接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始缩减,最终为一个值。
reduce 为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:初始值(或者上一次回调函数的返回值),当前元素值,当前索引,调用 reduce 的数组。
语法:
arr.reduce(callback,[initialValue])
-
callback (执行数组中每个值的函数,包含四个参数)
- previousValue (上一次调用回调返回的值,或者是提供的初始值(initialValue))
- currentValue (数组中当前被处理的元素)
- index (当前元素在数组中的索引)
- array (调用 reduce 的数组)
- initialValue (作为第一次调用 callback 的第一个参数。)
参考【https://segmentfault.com/a/1190000010731933?utm_source=tag-newest】
2、JS:Object.assign()方法
Object.assign()
方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
Object.assign(target, ...sources);
参数:
- target: 目标对象
- sources: 源对象
返回值:
*目标对象
Object.assign
方法只会拷贝源对象自身的并且可枚举的属性到目标对象。该方法使用源对象的[[Get]]
和目标对象的[[Set]]
,所以它会调用相关 getter 和 setter。因此,它分配属性,而不仅仅是复制或定义新的属性。如果合并源包含getter,这可能使其不适合将新属性合并到原型中。为了将属性定义(包括其可枚举性)复制到原型,应使用Object.getOwnPropertyDescriptor()
和Object.defineProperty()
。String
类型和Symbol
类型的属性都会被拷贝。在出现错误的情况下,例如,如果属性不可写,会引发
TypeError
,如果在引发错误之前添加了任何属性,则可以更改target
对象。注意,
Object.assign
不会跳过那些值为 [null
] 或 [undefined
]的源对象。例子:
const object1 = {
a: 1,
b: 2,
c: 3
};
const object2 = Object.assign({c: 4, d: 5}, object1);
console.log(object2.c, object2.d);
// expected output: 3 5
----------------------------------------------------------
【对象转数组】
【需求】如何把一个对象{'未完成':5, '已完成':8, '待确认':4, '已取消':6}转为[{"未完成":5},{"已完成":8},{"待确认":4},{"已取消":6}]
【解答】
let obj = {'未完成':5, '已完成':8, '待确认':4, '已取消':6};
var arr = [] ;
for (let i in obj) {
let o = {};
o[i] = obj[i];
arr.push(o)
}
console.log(arr);