【问题标题】:Mapping answers based on an ID根据 ID 映射答案
【发布时间】:2021-12-17 20:15:37
【问题描述】:

我有一个对象数组用于这样的测验。

[
    {
        answer: "Patience"
        question: "Name a GNR song..."
        questionId: 13
        questiontype: "text"
        userId: 1
    },
    {
        answer: "ABC"
        question: "Select three MJ songs..."
        questionId: 14
        questiontype: "checkbox"
        userId: 1
    },
    {
        answer: "Thriller"
        question: "Name three MJ songs..."
        questionId: 14
        questiontype: "checkbox"
        userId: 1
    }
]

我想做的是将它们显示在页面上。所以目前我正在做这样的事情

{quizData.map((item, index) => {
  return (
    <div key={index}>
      <Col xs={12}>
        <p className="text-start quiz-text">
          <strong>
            Question {item.question}
          </strong>
        </p>
      </Col>
      <Col xs={12}>
        <p className="text-start argent c-font quiz-text">{item.answer}</p>
      </Col>
    </div>
  );
})}

问题是这将为每个答案显示一个新的问题行。所以对于上面的数据,我看到是这样的

Name a GNR song
    Patience

Select 3 MJ songs
    ABC
    
Select 3 MJ songs
    Thriller

我想要做的是只有一个问题,但如果该问题有多个答案,请将这些显示为该问题的一部分。所以上面会是这样的

Name a GNR song
    Patience

Select 3 MJ songs
    ABC
    Thriller

我想我必须以某种方式匹配 questionId,但不确定如何在我的地图中实现这一点?

任何建议表示赞赏。

谢谢

【问题讨论】:

  • 您如何存储多个答案?用逗号分隔的字符串?

标签: javascript reactjs ecmascript-6


【解决方案1】:

您可以使用 array.filter() 或 for 循环来修改数组 berfore implementation 。在 jsx 中的 map 中实现之前,您必须制作正确的数组

【讨论】:

    【解决方案2】:

    如果您可以控制的话,我会亲自更改数据结构以将问题和答案分开。

    但是,如果你不这样做,你可以这样做:

    {quizData.map((item, index) => {
      return (
        <div key={index}>
          <Col xs={12}>
            <p className="text-start quiz-text">
              <strong>
                Question {item.question}
              </strong>
            </p>
          </Col>
          <Col xs={12}>
            {quizData.filter(answer => answer.questionId === item.questionId).map(answer => {
              return <p>{ answer.answer }</p>
            })}
          </Col>
        </div>
      );
    })}

    ^^ 这将产生重复的静止图像

    解决方案:

    const ComponentName = () => {
      const questions = [
        {
          id: 13,
          question: "Name a GNR song..."
        }
      ]
    
      const answers = [
        {
          id: 1,
          questionId: 13
          answer: "Patience"
          questiontype: "text"
        }
      ]
      
      return (
        <div>
        
          {questions.map((question, index) => {
            return (
              <div key={index}>
                <Col xs={12}>
                  <p className="text-start quiz-text">
                    <strong>
                      Question {question.question}
                    </strong>
                  </p>
                </Col>
                <Col xs={12}>
                  {answers.filter(answer => answer.questionId === question.id).map(answer => {
                    return <p className="text-start argent c-font quiz-text">{answer.answer}</p>
                  })}
                </Col>
              </div>
            );
          })}
        
        </div>
      )
      
    }

    如果您可以像我在这里显示的那样修改数据,这应该可以解决您的问题

    【讨论】:

    • 我在第一个答案中犯了一个错误,我没有意识到您没有每个问题的 ID,所以我更改了过滤器以使用不同的属性
    • 谢谢,这很有帮助。它将所有答案放在一个问题下,但它仍然是重复问题。因此,如果一个问题有 3 个答案,我现在会看到该问题 3 次,每次都有 3 个答案。所以我认为我需要以某种方式将 item.question 包含在某个地方?
    • 实际上,尽管如此,您确实应该更改数据结构,因为即使使用我上面的示例,您也会有重复。您需要将问题和答案放在两个不同的数组中,然后您可以 .filter 每个问题的答案数组以获得该问题的答案
    • 我为您重新编辑了答案,如果您可以编辑数据,那应该可以工作
    【解决方案3】:

    您可以首先使用 Map Constructor 将唯一的问题 ID 放入数组中,如下所示:

    var uniqueQIDs = [...new Map(data.map(obj => [obj.questionId, obj])).values()].map(obj => obj.questionId);
    

    然后您可以循环每个问题 ID 并根据以下内容过滤您的原始数据:

    {uniqueQIDs.map((qID, index) => {
      return (
        <div key={index}>
          <Col xs={12}>
            <p className="text-start quiz-text">
              <strong>
                Question {qID}
              </strong>
            </p>
          </Col>
          <Col xs={12}>
            {quizData.filter(obj => obj.questionId === qID).map(obj => {
              return <p>{ obj.answer }</p>
            })}
          </Col>
        </div>
      );
    })}
    

    【讨论】:

      【解决方案4】:

      您要做的是按 questionId 对数组的每个对象进行分组。因此,为了做到这一点,您可以通过以下方式实现groupBy() 中提到的this answer 的香草版本

      const groupBy = (list, keyGetter) => {
          const map = new Map();
          list.forEach((item) => {
               const key = keyGetter(item);
               const collection = map.get(key);
               if (!collection) {
                   map.set(key, [item]);
               } else {
                   collection.push(item);
               }
          });
          return map;
      }
      

      之后你可以简单地使用它

      // list of your question objects
      var questions = [
          {
              answer: "Patience",
              question: "Name a GNR song...",
              questionId: 13,
              questiontype: "text",
              userId: 1,
          },
          {
              answer: "ABC",
              question: "Select three MJ songs...",
              questionId: 14,
              questiontype: "checkbox",
              userId: 1,
          },
          {
              answer: "Thriller",
              question: "Name three MJ songs...",
              questionId: 14,
              questiontype: "checkbox",
              userId: 1,
          }
      ];
      
      // groupBy function here shall return a Map object having questionId as key and
      // list of objects having that questionId as value as specified in callback passed in
      const myMap = groupBy(questions, x => x.questionId)
      
      // Now you can simply iterate over the myMap object by using forEach
      myMap.forEach(
          group => { // group is the list of objects having same questionId
              console.log(group[0].question);
              group.map( // you can simply map your group like this
                  object => console.log("   ", object.answer) 
              )
          }
      )
      
      // OUTPUT:
      
      // Name a GNR song...
      //     Patience
      // Select three MJ songs...
      //     ABC
      //     Thriller
      

      More about Map forEach

      【讨论】:

        猜你喜欢
        • 2020-08-01
        • 1970-01-01
        • 2022-11-24
        • 2021-05-05
        • 1970-01-01
        • 2011-05-17
        • 2022-10-30
        • 1970-01-01
        • 2020-11-19
        相关资源
        最近更新 更多