在没有太多嵌套循环的情况下在多维数组中查找匹配元素?

Find matching elements in multi dimensional arrays without too many nested loops?

我有一个包含三层嵌套的数组和一个一维 object.I 需要比较两者以找到匹配的 ID 并将它们成对放入新数组。我只是在这里使用 map 方法,但也许有更有效的方法来做到这一点?我想过使用 filter 方法,但我认为它在这种情况下行不通。

函数:

const getMatchingIDs = function (pages, storedOBJ)  {
    const arr = []

    pages.map((page)=> {
        return page.questions.map((q)=>{
            const questionText = q.questionText

            return Object.keys(storedOBJ).map((key) => {
                const answerIndex = storedOBJ[key]

                if (typeof answerIndex !== 'undefined' && questionText === key) {
                    const answerID = q.answers[answerIndex].id
                    arr.push( q.id +  ':' + answerID)
                }
            })
        })
    })
    return arr
}

数组和对象:

const pages = [
{
    questions: [
        {
            id: 987,
            questionText: 'Some Question',
            answers: [
                {
                    id: 154
                },
                {
                    id: 232
                },
                {
                    id: 312
                }
            ]
        },
        {
            id: 324,
            questionText: 'Another Question',
            answers: [
                {
                    id: 154
                },
                {
                    id: 232
                },
                {
                    id: 312
                }
            ]
        },
        {
            id: 467,
            questionText: 'Last Question',
            answers: [
                {
                    id: 154
                },
                {
                    id: 232
                },
                {
                    id: 312
                }
            ]
            }
        ]
    }
]

const storedOBJ = {
    'Some Question': 0,
    'Last Question': 0,
    'Another Question': 2
}

运行 getMatchingIDs(pages, storedOBJ) 应该 return ["987:154", "324:312", "467:154"]

您对'map'

的使用

因此,一方面,您使用的是 'map' 方法,而使用 'forEach' 或 'reduce' 等其他数组方法会更好。传递给 'map' 方法的函数应该 return 新数组的一个元素。您正在使用 'map' 方法只是为了迭代数组而不捕获结果。

示例 #1

这里是您的 'matchIDs' 函数的略微修改版本。第一个 reduce 将页面展平以制作一个问题列表。第二个 reduce 生成你的匹配项,并跳过答案索引未定义的条件。

function matchIDs(pages, answerMap) {
  const questions = pages.reduce((questions, page) => { return questions.concat(page.questions) }, []);

  return questions.reduce((matches, question) => {
    const answerIndex = answerMap[question.questionText];
    if(typeof answerIndex != 'undefined') matches.push(`${question.id}:${question.answers[answerIndex].id}`);
    return matches;
  }, []);
}

示例 #2

在您的示例数据中,您只有一页,而且您的所有答案索引都是有效的。如果您可以做出这些假设,您可以进一步简化:

function matchIDs(questions, answerMap) {
  return questions.map(question => {
    const answerIndex = answerMap[question.questionText];
    return `${question.id}:${question.answers[answerIndex].id}`;
  });
}

可运行代码段

const pages = [
  {
    questions: [
      {
        id: 987,
        questionText: 'Some Question',
        answers: [
          {
            id: 154
          },
          {
            id: 232
          },
          {
            id: 312
          }
        ]
      },
      {
        id: 324,
        questionText: 'Another Question',
        answers: [
          {
            id: 154
          },
          {
            id: 232
          },
          {
            id: 312
          }
        ]
      },
      {
        id: 467,
        questionText: 'Last Question',
        answers: [
          {
            id: 154
          },
          {
            id: 232
          },
          {
            id: 312
          }
        ]
      }
    ]
  }
];

const storedOBJ = {
  'Some Question': 0,
  'Last Question': 0,
  'Another Question': 2
};

function matchIDs(pages, answerMap) {
  const questions = pages.reduce((questions, page) => { return questions.concat(page.questions) }, []);

  return questions.reduce((matches, question) => {
    const answerIndex = answerMap[question.questionText];
    if(typeof answerIndex != 'undefined') matches.push(`${question.id}:${question.answers[answerIndex].id}`);
    return matches;
  }, []);
}

function matchIDsAlt(questions, answerMap) {
  return questions.map(question => {
    const answerIndex = answerMap[question.questionText];
    return `${question.id}:${question.answers[answerIndex].id}`;
  });
}

console.log(matchIDs(pages, storedOBJ));
console.log(matchIDsAlt(pages[0].questions, storedOBJ));