根据 ID 映射答案

Mapping answers based on an ID

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

[
    {
        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,但不确定如何在我的地图中实现这一点?

感谢任何建议。

谢谢

您可以使用 array.filter() 或 for 循环在实现之前修改数组。在 jsx

中的 map 中实现之前必须创建正确的数组

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

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

{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>
  )
  
}

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

您可以先使用 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>
  );
})}

您要做的是按 questionId 对数组的每个对象进行分组。因此,为了做到这一点,您可以通过以下方式

实现 this answer 中提到的普通版本 groupBy()
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