使用Javascript将对象数组映射到非重复值对象

使用Javascript将对象数组映射到非重复值对象,javascript,arrays,object,filter,Javascript,Arrays,Object,Filter,我试图找到一种方法来转换JS对象上的主题列表,以便创建一个没有重复值的过滤器 到目前为止,我设法将唯一值映射并过滤到两个单独的数组中。我设法编写的代码是基本的(并没有解决问题): 所以我的主题的形状是这样的: var subjects = [ { "topic" : "Social Sciences", "subtopic" : "Developmental Issues" }, { "topic" : "Social Sciences", "subtopic" : "Gener

我试图找到一种方法来转换JS对象上的主题列表,以便创建一个没有重复值的过滤器

到目前为止,我设法将唯一值映射并过滤到两个单独的数组中。我设法编写的代码是基本的(并没有解决问题):

所以我的主题的形状是这样的:

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"
         }
     }

对象键应该是唯一的。一个对象中不能有多个同名键。一种选择是使用数组来代替
子主题

使用
reduce
将数组分组为一个对象。对子主题使用
new Set()
,以获得唯一值。使用
Object.values
将对象转换为数组

映射
数组,并使用扩展语法将集合转换为数组

var主题=[{“主题”:“社会科学”,“次主题”:“发展问题”},{“主题”:“社会科学”,“次主题”:“一般”},{“主题”:“一般”},{“主题”:“社会科学”,“次主题”:“一般和其他”},{“主题”:“社会科学”,“次主题”:“艺术”},{“主题”:“社会科学”,“次主题”:“历史”},{“主题”:“艺术与人文”、“副标题”:“历史”},{“主题”:“艺术与人文”、“副标题”:“文学”}];
var filter=Object.values(subjects.reduce)(c,v)=>{
c[v.topic]=c[v.topic]|{名称:v.topic,子主题:new Set()};
c[v.topic].副标题.添加(v.subtopic);
返回c;
},{})。映射(o=>{
o、 副标题=[…o.副标题];
返回o;
})

console.log(filter);
在一个对象中不能多次使用同一个键,因此您可以为
子主题创建一个数组结构,并使用
reduce
将匹配的
子主题推到那里:

var主题=[{
“主题”:“社会科学”,
“次主题”:“发展问题”
}, {
“主题”:“社会科学”,
“副标题”:“概述”
}, {
“主题”:“社会科学”,
“副标题”:“概述”
}, {
“主题”:“社会科学”,
“副标题”:“概述和其他”
},{
“主题”:“社会科学”,
“副标题”:“艺术”
},{
“主题”:“社会科学”,
“副标题”:“历史”
}, {
“主题”:“艺术与人文”,
“副标题”:“历史”
}, {
“主题”:“艺术与人文”,
“副标题”:“文学”
} ];
var过滤器=主体。减少(功能(acc,主体){
var accTopic=acc.find(item=>item.name==subject.topic);
如果(!accTopic){
acc.push({'name':subject.topic,'subtopic':[subject.subtopic]});
返回acc;
}否则{
accTopic.subtopic.push(subject.subtopic);
返回acc;
}
},[]);
console.log(过滤器);

因为同一对象上不能有相同的键,如果可以的话,我用子主题制作了一个数组。

使用
array.prototype.reduce
按主题对数据进行分组,然后使用
object.keys
array.prototype.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 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);

回答很好,但与前面提到的将唯一值过滤到两个单独数组的方法不同。好的一点是,还要注意,在对象中,顺序是不确定的。如果元素的顺序很重要,则应使用数组。例如{a:1,b:2}如果你在循环中创建,顺序是不保证的。只是帮助一个兄弟获得最佳答案;)嘿,谢谢你的建议。我遇到的问题是,我会重复一些副标题
“发展问题”1:“一般”2:“一般”3:“一般”和其他“4:“艺术”5:“历史”“
是的,如果子主题不存在,您可以创建条件,然后添加它:类似这样的内容:if(!topic.subtopics.find(sub=>sub==v.subtopic)){topic.subtopics.push(v.subtopic)}嘿,谢谢您在这方面的帮助。现在我学到了更多关于表达的知识。现在我正在使用这个解决方案,仍然需要弄清楚如何使用双绑定。。。。由于在复选框中使用了子主题,我需要在没有子主题的情况下禁用所有主题的结果(或者反过来说:当取消对主题的检查时,必须取消对所有子主题的检查)
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
}, [])
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);