JavaScript - 如何将数组列表转换为另一个键值对数组列表?

3

我很久以来都为这个问题烦恼,并且无法找到一个优雅的解决方案。假设我有如下数组:

[
   {
     question: "what is your name?",
     answer: "Ben",
     topic: "names"
   },
{
     question: "what is your name?",
     answer: "Ben",
     topic: "names"
   },
   {
     question: "What is dog's name?",
     answer: "Snugglets",
     topic: "names"
   },
   {
     question: "What is your brother's age?",
     answer: 55,
     topic: "ages"
   }
]

我该如何将它转换成这样的数组?
[
   {
     topic: "names",
     content: [...array of objects based on "names"...]
   },
{
     topic: "ages",
     content: [...array of objects based on "ages"...]
   }
]

我觉得这应该是一件非常简单的事情,但由于某些原因,我的大脑似乎无法掌握解决方案。我错过了什么?
更新:感谢所有回复!我没有想到会得到这么多完成此任务的方法。我接受了其中一个答案,因为它与ES6有关,我应该明确指出我正在寻找ES6的做法,如果可能的话 :)
尽管如此,我必须说需求也有所改变,不再是原来意图的数组,像这样:
[ { topic: "names", content: [...基于“名称”的对象数组...] }, { topic: "ages", content: [...基于“年龄”的对象数组...] } ]
数组需要看起来更像这样:
[ { topic: "names", content: '<div> <h3>问题:你的名字是什么?</h3> <p>答案:本</p> </div> <div> <h3>问题:你狗的名字是什么?</h3> <p>答案:Snugglets</p> </div>' }, { topic: "ages", content: content: '<div> <h3>问题:你的年龄是多少?</h3> <p>答案:50</p> </div> <div> <h3>问题:你兄弟的年龄是多少?</h3> <p>答案:52</p> </div>' } ]
通常情况下,我不喜欢只是要求给我代码,但是当涉及到算法转换数据时,我的JavaScript技能似乎有点弱 :( 你有什么想法可以将所有这些数组元素合并为一个包含HTML的字符串,作为每个“主题”的“内容”键?此外,这个问题是否更适合在Stackoverflow上提出?
5个回答

3
你可以使用一个临时对象将其分组,并使用 Array#forEach 进行迭代。

forEach() 方法对数组中的每个元素执行一次提供的函数。

var data = [{ question: "what is your name?", answer: "Ben", topic: "names" }, { question: "what is your name?", answer: "Ben", topic: "names" }, { question: "What is dog's name?", answer: "Snugglets", topic: "names" }, { question: "What is your brother's age?", answer: 55, topic: "ages" }],
    group = [];

data.forEach(function (a) {
    if (!this[a.topic]) {
        this[a.topic] = { topic: a.topic, content: [] };
        group.push(this[a.topic]);
    }
    this[a.topic].content.push(a);
}, Object.create(null));

console.log(group);


我认为他想要推送 ({question: a.question, answer: a.answer}) 而不仅仅是 (a.answer) - Florian Lemaitre

1
当使用ES6 Map对象时,可以简单地按照以下方式完成。我还从content数组的项目中删除了冗余的names属性。

var data = [{question: "what is your name?",answer: "Ben",topic: "names"},{question: "what is your name?",answer: "Ben",topic: "names"},{question: "What is dog's name?",answer: "Snugglets",topic: "names"},{question: "What is your brother's age?",answer: 55,topic: "ages"}],
 mapData = data.reduce((p,c) => p.has(c.topic) ? p.set(c.topic,p.get(c.topic).concat({question:c.question,
                                                                                        answer:c.answer}))
                                               : p.set(c.topic,[{question:c.question,
                                                                   answer:c.answer}]),new Map()),
  result = [...mapData].map(e => ({topic:e[0],content:e[1]}));
console.log(result);


1
一个更加实用的方法是使用Array.reduce。这也消除了临时变量的需要:
var output = data.reduce(function(prev, cur) {
  if (!prev[cur.topic]) prev[cur.topic] = [];
  prev[cur.topic].push(cur);
  return prev;
}, {});

请参见JS Bin工作示例:
https://jsbin.com/yesucaquwa/1/edit?js,console


0

试试这个:

var input = [
   {
     question: "what is your name?",
     answer: "Ben",
     topic: "names"
   },
{
     question: "what is your name?",
     answer: "Ben",
     topic: "names"
   },
   {
     question: "What is dog's name?",
     answer: "Snugglets",
     topic: "names"
   },
   {
     question: "What is your brother's age?",
     answer: 55,
     topic: "ages"
   }
];
var tmp = input.reduce(function(topics, obj) {
  topics[obj.topic] = topics[obj.topic] || {topic: obj.topic, content: []};
  topics[obj.topic].content.push(obj);
  return topics;
}, {});
var output = Object.keys(tmp).map(function(key) {
  return tmp[key];
});
console.log(output);


-1

这里有一个简单的函数供您使用。

var arr=[
   {
     question: "what is your name?",
     answer: "Ben",
     topic: "names"
   },
    {
     question: "what is your name?",
     answer: "Ben",
     topic: "names"
   },
   {
     question: "What is dog's name?",
     answer: "Snugglets",
     topic: "names"
   },
   {
     question: "What is your brother's age?",
     answer: 55,
     topic: "ages"
   }
]
function turnToOtherArray(arr){
    var result=[];
    for(var i=0,mamorize={};i<arr.length;i++){
        if(mamorize[arr[i].topic]){
            mamorize[arr[i].topic].push(arr[i].question)
        }else{
            mamorize[arr[i].topic]=[arr[i].question]
        }
    }
    for(var key in mamorize){
        result[result.length] = { "topic" : key , "content" : mamorize[key]}
    }
    return result;
}
console.log(turnToOtherArray(arr));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接