如何在我的特定情况下形成嵌套数组的数组?

Posted

技术标签:

【中文标题】如何在我的特定情况下形成嵌套数组的数组?【英文标题】:How to form an array of nested arrays in my specific case? 【发布时间】:2021-09-07 19:41:47 【问题描述】:

我有一个特定的用例,我想将一个数组中的所有对象组合成一个新数组。所以我在我的网站上有一个表格,用户在预订时正在添加参与者。他们可以根据需要添加任意数量的参与者。我将它们以 JSON 格式保存在数据库中,现在我想形成一个包含所有参与者的数组,以便可以将它们全部显示在表格中。

所以我首先从一个特定列表中获取所有交易,这些交易作为一个对象数组获得,然后我循环遍历它们,只获得包含每个交易参与者的transaction.attributes.protectedData.questions

所以我的交易对象看起来像:

[
   
      "type":"transaction",
      "attributes":
         "createdAt":"2021-06-24T08:50:26.911Z",
         "protectedData":
            "questions":[
               [
                  
                     "question":"name",
                     "answer":"Mario North"
                  ,
                  
                     "question":"email",
                     "answer":"mario@gmail.com"
                  
               ]
            ],
            "ticketType":
               "name":"Main entry",
               "quantity":1
            
         
      
   ,
   
      "type":"transaction",
      "attributes":
         "createdAt":"2021-06-24T08:48:57.646Z",
         "protectedData":
            "questions":[
               [
                  
                     "question":"name",
                     "answer":"John Adkins"
                  ,
                  
                     "question":"email",
                     "answer":"john@gmail.com"
                  
               ],
               [
                  
                     "question":"name",
                     "answer":"Thomas Smith"
                  ,
                  
                     "question":"email",
                     "answer":"thomas@gmail.com"
                  
               ]
            ],
            "ticketType":
               "name":"General entry",
               "quantity":2
            
         
      
   
]

所以我需要遍历每个事务,然后遍历问题,问题数组中的每个新数组都是一个新参与者。在每个参与者中,我需要保存交易属性中的 createdAt 和 ticketType 值。

所以我的最终数组/对象需要如下所示:

[
   
      "createdAt":"2021-06-24T08:50:26.911Z",
      "ticketType":"Main entry",
      "name":"Mario North",
      "email":"mario@gmail.com"
   ,
   
      "createdAt":"2021-06-24T08:48:57.646Z",
      "ticketType":"General entry",
      "name":"John Adkins",
      "email":"john@gmail.com"
   ,
   
      "createdAt":"2021-06-24T08:48:57.646Z",
      "ticketType":"General entry",
      "name":"Thomas Smith",
      "email":"thomas@gmail.com"
   
]

所以我可以得到参与者列表,每个参与者都添加了 createdAt 和 ticketType。但我不知道如何才能让我的问题/答案显示为我在上面发布的我想要的对象。这就是我所拥有的:

export const denormalisedParticipantList = transactions => 
  let participants = [];

  transactions.map(transaction => 
    const createdAt = transaction.attributes.createdAt;
    const questions = transaction.attributes.protectedData?.questions;
    const ticketType = transaction.attributes.protectedData?.ticketType?.name;

    return questions.map(q => 
      // Form new participant object
      const participant = 
        createdAt,
        ticketType,
        ...Object.fromEntries(q.map(( question, answer ) => [question, answer])),
      ;

      // Push new participant
      participants.push(participant);
    );
  );

  return participants;
;

从昨晚开始,我一直在努力解决这个问题,但我无法让它发挥作用。谁能帮我弄清楚如何从我的交易对象中创建一个最终数组,我将非常感激。

【问题讨论】:

显示您的尝试,以便我们了解您如何尝试修复它。 我会把它贴在我的问题的底部。谢谢! 【参考方案1】:

Destructuring 可以成为跟踪您在复杂对象中访问的内容的有效方法。这里使用flatMap() 返回单个扁平数组,Object.fromEntries()questions 数组映射到单个对象。

const input = [ "type": "transaction", "attributes":  "createdAt": "2021-06-24T08:50:26.911Z", "protectedData":  "questions": [[ "question": "name", "answer": "Mario North" ,  "question": "email", "answer": "mario@gmail.com" ]], "ticketType":  "name": "Main entry", "quantity": 1    ,  "type": "transaction", "attributes":  "createdAt": "2021-06-24T08:48:57.646Z", "protectedData":  "questions": [[ "question": "name", "answer": "John Adkins" ,  "question": "email", "answer": "john@gmail.com" ], [ "question": "name", "answer": "Thomas Smith" ,  "question": "email", "answer": "thomas@gmail.com" ]], "ticketType":  "name": "General entry", "quantity": 2    ]

const result = input.flatMap((
  
    attributes: 
      createdAt,
      protectedData: 
        questions,
        ticketType:  name: ticketType  
    
  
) => (
  questions.map(p => (
    createdAt,
    ticketType,
    ...Object.fromEntries(p.map(( question, answer ) => [question, answer]))
  ))
));

console.log(result)
.as-console-wrapper  max-height: 100% !important; top: 0; 

【讨论】:

嘿 pilchard,您的解决方案完美运行,而且非常干净。太感谢了。你能解释一下使用 flatMap 而不是我在问题中发布的方式有什么区别吗?我刚刚编辑了它。我也应该使用 flatMap 吗? 您在代码中使用了map(),但没有使用返回的数组。这是低效的,但是因为您手动将每个嵌套对象推送到结果数组,所以您最终不会得到嵌套数组。您应该将您的 map() 调用替换为 forEach() 或利用地图的返回值。 感谢 cmets 沙丁鱼。我已将您的答案标记为已接受。 不用担心,很高兴它有所帮助。【参考方案2】:
var array = []
data.forEach((element) => 
var object =  created: null,ticketType: null,name: null,email: null 
object.created = element.attributes.createdAt;
object.ticketType = element.attributes.protectedData.ticketType.name;
var tmp_data = element.attributes.protectedData.questions;
tmp_data.forEach((tmp) => 
    tmp.forEach((item) => 
        if(item.question == "name")
            object.name = item.answer;
        else
            object.email = item.answer;
        
    )
    array.push(object);
)
)

试试这个:)

【讨论】:

非常感谢 Michel,您的回答也有帮助!看起来真的很干净。如果我在我的 React 项目中使用这种 javascript 类型的答案可以吗?【参考方案3】:

您可以简单地使用reducemap

const data = [ "type": "transaction", "attributes":  "createdAt": "2021-06-24T08:50:26.911Z", "protectedData":  "questions": [[ "question": "name", "answer": "Mario North" ,  "question": "email", "answer": "mario@gmail.com" ]], "ticketType":  "name": "Main entry", "quantity": 1    ,  "type": "transaction", "attributes":  "createdAt": "2021-06-24T08:48:57.646Z", "protectedData":  "questions": [[ "question": "name", "answer": "John Adkins" ,  "question": "email", "answer": "john@gmail.com" ], [ "question": "name", "answer": "Thomas Smith" ,  "question": "email", "answer": "thomas@gmail.com" , "question": "gender", "answer": "male" ]], "ticketType":  "name": "General entry", "quantity": 2    ]


const output = data.reduce(
  (a, b) => [
    ...a,
    ...b.attributes.protectedData.questions.map(e => (
      createdAt: b.attributes.createdAt,
      ticketType: b.attributes.protectedData.ticketType.name,
      ...e.reduce((acc, cur) => ( ...acc, [cur.question]: cur.answer ), ),
    )),
  ],
  []
);

console.log(output);
.as-console-wrapper  max-height: 100% !important; top: 0; 

【讨论】:

非常感谢,这看起来很干净。如果我有更多问题该怎么办(因为有时姓名和电子邮件不是唯一的问题)。有没有办法动态制作它们? @MiodragSumaric,是的,你可以。我更新了我的答案。您可以看到最后一项包含性别问题。

以上是关于如何在我的特定情况下形成嵌套数组的数组?的主要内容,如果未能解决你的问题,请参考以下文章

使用数组作为 GraphQL 查询的变量

如何在不破坏我的结构的情况下将特定单元格排除到 BigQuery 中的数组数组中?

如何在不改变的情况下更新对象数组的嵌套数组的状态

如何在不创建嵌套数组的情况下将多个变量添加到数组

在我的情况下,如何使用批处理文件脚本制作数组列表?

如何在嵌套数组(数组中的数组)上使用 v-for 指令进行迭代