我试图找到一种方法来转换JS对象上的主题列表,以便创建一个没有重复值的过滤器。
到目前为止,我设法将唯一值映射并过滤到两个单独的数组中。我设法编写的代码是基本代码(不能解决问题):
var topic = subject
.map(function (value) { return value.topic })
.filter(function (elem, index, self) {
return index == self.indexOf(elem);
});
所以我的主体形状如下:
var subjects = [ {
"topic" : "Social Sciences",
"subtopic" : "Developmental Issues"
}, {
"topic" : "Social Sciences",
"subtopic" : "General"
}, {
"topic" : "Social Sciences",
"subtopic" : "General"
}, {
"topic" : "Social Sciences",
"subtopic" : "General and Others"
},{
"topic" : "Social Sciences",
"subtopic" : "Arts"
},{
"topic" : "Social Sciences",
"subtopic" : "History"
}, {
"topic" : "Arts and Humanities",
"subtopic" : "History"
}, {
"topic" : "Arts and Humanities",
"subtopic" : "Literature"
} ]
我需要创建一个看起来像这样的过滤器:
filter = [{
name: "Social Sciences",
{
subtopic: "Developmental Issues",
subtopic: "General",
subtopic: "General and Others",
subtopic: "Arts",
subtopic: "History"
}
}, {
name: "Arts and Humanities",
{
subtopic: "History",
subtopic: "Literature"
}
}
答案 0 :(得分:0)
对象键应该是唯一的。一个对象中不能有多个具有相同名称的键。一种选择是将数组用于subtopic
。
使用reduce
将数组分组为一个对象。将new Set()
用于子主题可获取唯一值。使用Object.values
将对象转换为数组。
map
数组,并使用扩展语法将集合转换为数组。
var subjects = [{"topic":"Social Sciences","subtopic":"Developmental Issues"},{"topic":"Social Sciences","subtopic":"General"},{"topic":"Social Sciences","subtopic":"General"},{"topic":"Social Sciences","subtopic":"General and Others"},{"topic":"Social Sciences","subtopic":"Arts"},{"topic":"Social Sciences","subtopic":"History"},{"topic":"Arts and Humanities","subtopic":"History"},{"topic":"Arts and Humanities","subtopic":"Literature"}];
var filter = Object.values(subjects.reduce((c, v) => {
c[v.topic] = c[v.topic] || {name: v.topic,subtopic: new Set()};
c[v.topic].subtopic.add(v.subtopic);
return c;
}, {})).map(o => {
o.subtopic = [...o.subtopic];
return o;
})
console.log(filter);
答案 1 :(得分:0)
您不能在一个对象中多次使用相同的键,因此您可以为subtopic
创建一个数组结构,然后使用subtopic
将匹配的reduce
推入那里:
var subjects = [ {
"topic" : "Social Sciences",
"subtopic" : "Developmental Issues"
}, {
"topic" : "Social Sciences",
"subtopic" : "General"
}, {
"topic" : "Social Sciences",
"subtopic" : "General"
}, {
"topic" : "Social Sciences",
"subtopic" : "General and Others"
},{
"topic" : "Social Sciences",
"subtopic" : "Arts"
},{
"topic" : "Social Sciences",
"subtopic" : "History"
}, {
"topic" : "Arts and Humanities",
"subtopic" : "History"
}, {
"topic" : "Arts and Humanities",
"subtopic" : "Literature"
} ];
var filter = subjects.reduce(function(acc, subject){
var accTopic = acc.find(item => item.name === subject.topic);
if(!accTopic){
acc.push({'name': subject.topic, 'subtopic': [subject.subtopic]});
return acc;
} else {
accTopic.subtopic.push(subject.subtopic);
return acc;
}
},[]);
console.log(filter);
答案 2 :(得分:0)
let res = subjects.reduce((acc, v, i) => {
let topic = acc.find(item => item.name == v.topic)
if (! topic) {
topic = {name: v.topic, subtopics: []}
acc.push(topic)
}
topic.subtopics.push(v.subtopic)
return acc
}, [])
否则,您不能在同一个对象上使用相同的键,如果可以帮助您,则我用一个子主题组成一个数组。
答案 3 :(得分:0)
使用Array.prototype.reduce
按主题对数据进行分组,然后使用Object.keys
和Array.prototype.map
进行映射:
NOTE
:子主题的输出是Array
而不是Object
,因为对象的相同键将被覆盖。
var subjects = [{"topic":"Social Sciences","subtopic":"Developmental Issues"},{"topic":"Social Sciences","subtopic":"General"},{"topic":"Social Sciences","subtopic":"General"},{"topic":"Social Sciences","subtopic":"General and Others"},{"topic":"Social Sciences","subtopic":"Arts"},{"topic":"Social Sciences","subtopic":"History"},{"topic":"Arts and Humanities","subtopic":"History"},{"topic":"Arts and Humanities","subtopic":"Literature"}];
var datObj = subjects.reduce((all, {topic, subtopic}) => {
if (!all.hasOwnProperty(topic)) all[topic] = [];
all[topic].push(subtopic);
return all;
}, {});
var filter = Object.keys(datObj).map(topic => ({name: topic, subtopic: datObj[topic]}))
console.log(filter);