【问题标题】:Object Array map into non repeated value Object with Javascript使用Javascript将对象数组映射到非重复值对象
【发布时间】:2018-07-02 13:24:37
【问题描述】:

我正在尝试找到一种方法来转换 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"
         }
     }

【问题讨论】:

    标签: javascript arrays object filter


    【解决方案1】:

    对象键应该是唯一的。一个对象中不能有多个具有相同名称的键。一种选择是使用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);

    【讨论】:

    • 嘿,谢谢你帮我解决这个问题。现在我学到了更多关于表达式的知识。现在我正在使用这个解决方案,仍然必须弄清楚如何将它与双重绑定一起使用......并且由于在复选框上使用了子主题,所以当没有子主题(或其他)时,我将需要禁用所有主题的结果解决方法:取消选中主题时,必须取消选中所有子主题)
    【解决方案2】:

    您不能在一个对象中多次使用相同的键,因此您可以为subtopic 创建一个数组结构,然后使用reduce 将匹配的subtopic 推到那里:

    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);

    【讨论】:

      【解决方案3】:
      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
      }, [])
      

      如果对你有帮助的话,你不能在同一个对象上使用相同的键,我用子主题制作了一个数组。

      【讨论】:

      • 好的答案,但并不完全像 唯一值 过滤到两个单独的数组中 提到。
      • 好点,还要注意在对象中的顺序是不确定的。如果元素的顺序很重要,则应使用数组。例如 {a:1, b:2} 如果您创建 for in 循环,则无法保证顺序。
      • 只是帮助兄弟获得最佳答案;)
      • 您好,谢谢您的提议。我遇到的问题是我会重复一些子主题"Developmental Issues" 1 : "General" 2 : "General" 3 : "General and Others"4:"Arts"5:"History"
      • 是的,如果子主题不存在,您可以创建条件然后添加它:像这样: if ( ! topic.subtopics.find(sub => sub == v.subtopic)) { topic. subtopics.push(v.subtopic) }
      【解决方案4】:

      使用Array.prototype.reduce按主题对数据进行分组,然后用Object.keysArray.prototype.map映射出来:

      NOTE:subtopic 的输出是 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);
      

      【讨论】:

        猜你喜欢
        • 2018-12-04
        • 2020-11-09
        • 2019-08-25
        • 1970-01-01
        • 2022-11-24
        • 2021-07-07
        • 2020-07-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多