Найти подходящие элементы в многомерных массивах без слишком большого количества вложенных циклов? - PullRequest
0 голосов
/ 09 мая 2018

У меня есть массив с тремя уровнями вложенности и одномерный объект. Мне нужно сравнить два, чтобы найти совпадающие идентификаторы и вставить их в новый массив в виде пар. Я просто использую метод карты здесь, но, возможно, есть более эффективный способ сделать это? Я думал об использовании метода фильтра, но я не думаю, что он может работать в этом случае.

ФУНКЦИЯ:

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) должен вернуть ["987:154", "324:312", "467:154"]

1 Ответ

0 голосов
/ 10 мая 2018

Ваше использование карты

Итак, во-первых, вы используете метод 'map', где было бы лучше использовать другие методы массива, такие как 'forEach' или 'Reduce'. Функция, переданная методу map, должна возвращать элемент для нового массива. Вы используете метод 'map' только для итерации массивов без захвата результата.

Пример # 1

Вот немного измененная версия вашей функции 'matchIDs'. Первое сокращение сглаживает страницы, чтобы составить единый список вопросов. Второе сокращение производит ваши совпадения и пропускает условия, когда индекс ответа не определен.

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));
...