#javascript #arrays
Вопрос:
Я ищу все возможные пути ответов на вопросы, основанные на вариантах вопросов, я весь день ломал голову и, похоже, не могу понять, почему мой код не работает.
Тестовый код:
const originalQuestions = {
1: {
title: "Title",
firstQuestion: true,
options: [{
tooltip: "",
nextQuestion: 2
}, {
tooltip: "",
nextQuestion: 2
}, {
tooltip: "",
nextQuestion: 10000
}]
},
2: {
title: "Title",
options: [{
tooltip: "",
nextQuestion: 3
}, {
tooltip: "",
nextQuestion: 3
}, {
tooltip: "",
nextQuestion: 3
}, {
tooltip: "",
nextQuestion: 3
}]
},
3: {
title: "Title",
options: [{
tooltip: "",
nextQuestion: 4
}, {
tooltip: "",
nextQuestion: 4
}, {
tooltip: "",
nextQuestion: 4
}]
},
4: {
title: "Title",
options: [{
tooltip: "",
nextQuestion: 13
}, {
tooltip: "",
nextQuestion: 5
}]
},
5: {
title: "Title",
options: [{
tooltip: "",
nextQuestion: 6
}, {
tooltip: "",
nextQuestion: 6
}, {
tooltip: "",
nextQuestion: 6
}, {
tooltip: "",
nextQuestion: 10000
}]
},
6: {
title: "Title",
options: [{
tooltip: "",
nextQuestion: 7
}, {
tooltip: "",
nextQuestion: 7
}, {
tooltip: "",
nextQuestion: 7
}, {
tooltip: "",
nextQuestion: 7
}, {
tooltip: "",
nextQuestion: 14
}]
},
7: {
title: "Title",
options: [{
tooltip: "",
nextQuestion: 17
}, {
tooltip: "",
nextQuestion: 17
}, {
tooltip: "",
nextQuestion: 17
}, {
tooltip: "",
nextQuestion: 17
}, {
tooltip: "",
nextQuestion: 17
}]
},
8: {
title: "Title",
options: [{
tooltip: "",
nextQuestion: 9
}, {
tooltip: "",
nextQuestion: 9
}, {
tooltip: "",
nextQuestion: 9
}]
},
9: {
title: "Title",
options: [{
tooltip: "",
nextQuestion: 10
}, {
tooltip: "",
nextQuestion: 10
}, {
tooltip: "",
nextQuestion: 10
}]
},
10: {
title: "Title",
options: [{
tooltip: "",
nextQuestion: 11
}, {
value: "Roof",
attribute: "Flue Exit",
tooltip: "",
nextQuestion: 15
}]
},
11: {
title: "Title",
options: [{
tooltip: "",
nextQuestion: 12
}, {
tooltip: "",
nextQuestion: 12
}]
},
12: {
finalQuestion: true,
input: true,
placeHolder: 'e.g SWS'
},
13: {
title: "Title",
options: [{
tooltip: "",
nextQuestion: 6
}, {
tooltip: "",
nextQuestion: 6
}]
},
14: {
title: "Title",
options: [{
tooltip: "",
nextQuestion: 7
}, {
tooltip: "",
nextQuestion: 7
}, {
tooltip: "",
nextQuestion: 10000
}]
},
15: {
title: "Title",
options: [{
tooltip: "",
nextQuestion: 12
}, {
tooltip: "",
nextQuestion: 12
}]
},
17: {
title: "Title",
options: [{
tooltip: "",
nextQuestion: 8
}, {
tooltip: "",
nextQuestion: 8
}, {
tooltip: "",
nextQuestion: 8
}, {
tooltip: "",
nextQuestion: 8
}, {
tooltip: "",
nextQuestion: 8
}]
},
// Errors
10000: {
isError: true,
title: "Finally, what is the first part of your postcode?",
error: "Postcode"
}
};
function loopPaths(currentArrayPath, questionNum, currentQuestion, paths) {
if (questionNum > 5) {
return false;
}
if (typeof currentQuestion.finalQuestion != 'undefined') {
return false;
} else {
const question = currentQuestion.options;
const validPaths = question.filter((e) => e.nextQuestion !== 10000);
const clonedPath = [...paths[currentArrayPath][0]];
for (var i = 0; i < validPaths.length; i ) {
const e = validPaths[i];
if (typeof paths[currentArrayPath][i] == 'undefined') {
paths[currentArrayPath][i] = [...clonedPath];
}
paths[currentArrayPath][i].push(questionNum);
loopPaths(currentArrayPath, e.nextQuestion, originalQuestions[e.nextQuestion], paths);
}
}
}
function possiblePaths() {
const question1 = originalQuestions[1].options;
const validPaths = question1.filter((e) => e.nextQuestion !== 10000);
let paths = [];
/*validPaths.forEach((e, i) => {
paths[i] = [[1]];
});*/
/*
for (var i = 0; i < validPaths.length; i ) {
const e = validPaths[i];
loopPaths(e.nextQuestion, boilerQuestions[e.nextQuestion], paths);
} */
// Testing with first question, first option
paths[0] = [[1]];
loopPaths(0, 2, originalQuestions[2], paths);
console.log(paths);
}
possiblePaths();
Что, кажется, происходит: (Это не построение правильных путей и не построение различных возможностей)
[
[
[
1,
2,
3,
4,
5,
4,
5,
4,
5,
3,
4,
5,
4,
5,
4,
5,
3,
4,
5,
4,
5,
4,
5,
3,
4,
5,
4,
5,
4,
5
],
[
1,
2,
3,
4,
5,
3,
4,
5,
4,
5,
2,
4,
5,
3,
4,
5,
4,
5,
4,
5,
3,
4,
5,
4,
5,
4,
5,
3,
4,
5,
4,
5
]
]
]
Пример того, что он должен показать: (Мне интересно, есть ли более простой способ построить различные возможности от 1 -> до последнего вопроса, который равен 12)
[
[
[
1,
2,
3,
4,
13,
7,
17,
8,
9,
10,
11,
12
],
[
1,
2,
3,
4,
5,
6,
7,
....
]
]
]
Как это будет работать:
Пользователь нажимает вопрос 1 -> Нажимает вариант 1 ->> Пользователь нажимает вопрос 2 ->>> Нажимает вариант 2 ->>>> Пользователь нажимает вопрос 3 ->>>>> Нажимает вариант 1 — > > > > > > > Пользователь нажимает вопрос 4 — > > > > > > > > Нажимает вариант 1 ->>>>>>>> Пользователь задает вопрос 13
Ответ №1:
Вы можете использовать функцию рекурсивного генератора.
const originalQuestions = { 1: { title: "Title", firstQuestion: true, options: [{ tooltip: "", nextQuestion: 2 }, { tooltip: "", nextQuestion: 2 }, { tooltip: "", nextQuestion: 10000 }] }, 2: { title: "Title", options: [{ tooltip: "", nextQuestion: 3 }, { tooltip: "", nextQuestion: 3 }, { tooltip: "", nextQuestion: 3 }, { tooltip: "", nextQuestion: 3 }] }, 3: { title: "Title", options: [{ tooltip: "", nextQuestion: 4 }, { tooltip: "", nextQuestion: 4 }, { tooltip: "", nextQuestion: 4 }] }, 4: { title: "Title", options: [{ tooltip: "", nextQuestion: 13 }, { tooltip: "", nextQuestion: 5 }] }, 5: { title: "Title", options: [{ tooltip: "", nextQuestion: 6 }, { tooltip: "", nextQuestion: 6 }, { tooltip: "", nextQuestion: 6 }, { tooltip: "", nextQuestion: 10000 }] }, 6: { title: "Title", options: [{ tooltip: "", nextQuestion: 7 }, { tooltip: "", nextQuestion: 7 }, { tooltip: "", nextQuestion: 7 }, { tooltip: "", nextQuestion: 7 }, { tooltip: "", nextQuestion: 14 }] }, 7: { title: "Title", options: [{ tooltip: "", nextQuestion: 17 }, { tooltip: "", nextQuestion: 17 }, { tooltip: "", nextQuestion: 17 }, { tooltip: "", nextQuestion: 17 }, { tooltip: "", nextQuestion: 17 }] }, 8: { title: "Title", options: [{ tooltip: "", nextQuestion: 9 }, { tooltip: "", nextQuestion: 9 }, { tooltip: "", nextQuestion: 9 }] }, 9: { title: "Title", options: [{ tooltip: "", nextQuestion: 10 }, { tooltip: "", nextQuestion: 10 }, { tooltip: "", nextQuestion: 10 }] }, 10: { title: "Title", options: [{ tooltip: "", nextQuestion: 11 }, { value: "Roof", attribute: "Flue Exit", tooltip: "", nextQuestion: 15 }] }, 11: { title: "Title", options: [{ tooltip: "", nextQuestion: 12 }, { tooltip: "", nextQuestion: 12 }] }, 12: { finalQuestion: true, input: true, placeHolder: 'e.g SWS' }, 13: { title: "Title", options: [{ tooltip: "", nextQuestion: 6 }, { tooltip: "", nextQuestion: 6 }] }, 14: { title: "Title", options: [{ tooltip: "", nextQuestion: 7 }, { tooltip: "", nextQuestion: 7 }, { tooltip: "", nextQuestion: 10000 }] }, 15: { title: "Title", options: [{ tooltip: "", nextQuestion: 12 }, { tooltip: "", nextQuestion: 12 }] }, 17: { title: "Title", options: [{ tooltip: "", nextQuestion: 8 }, { tooltip: "", nextQuestion: 8 }, { tooltip: "", nextQuestion: 8 }, { tooltip: "", nextQuestion: 8 }, { tooltip: "", nextQuestion: 8 }] }, 10000: { isError: true, title: "Finally, what is the first part of your postcode?", error: "Postcode" } };
function* fnName(key, result = [key]) {
let options = originalQuestions[key]?.options;
if (!options) yield result
else for (const id of new Set(options.map(v => v.nextQuestion)))
yield* fnName(id, result.concat(id));
}
console.log("Prettify", Array.from(fnName(1), path => path.join(", ")))
Я просто передаю идентификатор 1-го вопроса ( fnName(1)
), в данном случае его номер 1
, потому что это 1-й вопрос. ( originalQuestions[1].firstQuestion = true
)
Ответ №2:
Пошлите несколько агентов, которые изучат ваши пути. Каждый агент отслеживает, где он был. Он также может клонировать себя, чтобы исследовать по нескольким путям:
class Agent {
constructor(questions, ...path){
//data fields
this.questions = questions;
this.path = path;
//derived fields
const currentStep = this.path[this.path.length-1];
this.currentQuetion = this.questions[currentStep];
this.isFinished =
this.currentQuetion.finalQuestion
|| this.currentQuetion.isError
|| false;
}
clone(andNextStep) {
return new Agent(this.questions, ...this.path, andNextStep);
}
possibleNext() {
const nextSteps = (this.currentQuetion.options ?? [])
.map(x => x.nextQuestion);
return new Set(nextSteps);
}
takeStep() {
if (this.isFinished)
return [this];
return Array.from(this.possibleNext(), step => this.clone(step));
}
static start(questions) {
//find any possible first questions
const first = Object.entries(questions)
.filter(([key, q]) => q.firstQuestion);
//for each first question create an agent
let pathExplorers = first.map(([start]) => new Agent(questions, start));
//get all agents to continue until they are all finished
while (pathExplorers.some(x => !x.isFinished))
pathExplorers = pathExplorers.flatMap(x => x.takeStep());
return pathExplorers;
}
}
const originalQuestions = { 1: { title: "Title", firstQuestion: true, options: [{ tooltip: "", nextQuestion: 2 }, { tooltip: "", nextQuestion: 2 }, { tooltip: "", nextQuestion: 10000 }] }, 2: { title: "Title", options: [{ tooltip: "", nextQuestion: 3 }, { tooltip: "", nextQuestion: 3 }, { tooltip: "", nextQuestion: 3 }, { tooltip: "", nextQuestion: 3 }] }, 3: { title: "Title", options: [{ tooltip: "", nextQuestion: 4 }, { tooltip: "", nextQuestion: 4 }, { tooltip: "", nextQuestion: 4 }] }, 4: { title: "Title", options: [{ tooltip: "", nextQuestion: 13 }, { tooltip: "", nextQuestion: 5 }] }, 5: { title: "Title", options: [{ tooltip: "", nextQuestion: 6 }, { tooltip: "", nextQuestion: 6 }, { tooltip: "", nextQuestion: 6 }, { tooltip: "", nextQuestion: 10000 }] }, 6: { title: "Title", options: [{ tooltip: "", nextQuestion: 7 }, { tooltip: "", nextQuestion: 7 }, { tooltip: "", nextQuestion: 7 }, { tooltip: "", nextQuestion: 7 }, { tooltip: "", nextQuestion: 14 }] }, 7: { title: "Title", options: [{ tooltip: "", nextQuestion: 17 }, { tooltip: "", nextQuestion: 17 }, { tooltip: "", nextQuestion: 17 }, { tooltip: "", nextQuestion: 17 }, { tooltip: "", nextQuestion: 17 }] }, 8: { title: "Title", options: [{ tooltip: "", nextQuestion: 9 }, { tooltip: "", nextQuestion: 9 }, { tooltip: "", nextQuestion: 9 }] }, 9: { title: "Title", options: [{ tooltip: "", nextQuestion: 10 }, { tooltip: "", nextQuestion: 10 }, { tooltip: "", nextQuestion: 10 }] }, 10: { title: "Title", options: [{ tooltip: "", nextQuestion: 11 }, { value: "Roof", attribute: "Flue Exit", tooltip: "", nextQuestion: 15 }] }, 11: { title: "Title", options: [{ tooltip: "", nextQuestion: 12 }, { tooltip: "", nextQuestion: 12 }] }, 12: { finalQuestion: true, input: true, placeHolder: 'e.g SWS' }, 13: { title: "Title", options: [{ tooltip: "", nextQuestion: 6 }, { tooltip: "", nextQuestion: 6 }] }, 14: { title: "Title", options: [{ tooltip: "", nextQuestion: 7 }, { tooltip: "", nextQuestion: 7 }, { tooltip: "", nextQuestion: 10000 }] }, 15: { title: "Title", options: [{ tooltip: "", nextQuestion: 12 }, { tooltip: "", nextQuestion: 12 }] }, 17: { title: "Title", options: [{ tooltip: "", nextQuestion: 8 }, { tooltip: "", nextQuestion: 8 }, { tooltip: "", nextQuestion: 8 }, { tooltip: "", nextQuestion: 8 }, { tooltip: "", nextQuestion: 8 }] }, 10000: { isError: true, title: "Finally, what is the first part of your postcode?", error: "Postcode" } };
const result = Agent.start(originalQuestions)
.map(agent => agent.path);
console.log(
//more concise printing
result.map(path => path
.map(step => String(step).padStart(2))
.join(" -> "))
);
Ответ №3:
Замечательный ответ Нура-это почти точно то, как бы я решил эту проблему. Я мог бы предложить несколько изменений, которые делают это достаточно другим, чтобы оправдать отдельный пост —
function* paths(t, key) {
const { options } = t[key] ?? {}
if (options == null) return yield [key]
for (const id of new Set(options.map(v => v.nextQuestion)))
for (const path of paths(t, id))
yield [key, ...path]
}
const originalQuestions =
{ 1: { title: "Title", firstQuestion: true, options: [{ tooltip: "", nextQuestion: 2 }, { tooltip: "", nextQuestion: 2 }, { tooltip: "", nextQuestion: 10000 }] }, 2: { title: "Title", options: [{ tooltip: "", nextQuestion: 3 }, { tooltip: "", nextQuestion: 3 }, { tooltip: "", nextQuestion: 3 }, { tooltip: "", nextQuestion: 3 }] }, 3: { title: "Title", options: [{ tooltip: "", nextQuestion: 4 }, { tooltip: "", nextQuestion: 4 }, { tooltip: "", nextQuestion: 4 }] }, 4: { title: "Title", options: [{ tooltip: "", nextQuestion: 13 }, { tooltip: "", nextQuestion: 5 }] }, 5: { title: "Title", options: [{ tooltip: "", nextQuestion: 6 }, { tooltip: "", nextQuestion: 6 }, { tooltip: "", nextQuestion: 6 }, { tooltip: "", nextQuestion: 10000 }] }, 6: { title: "Title", options: [{ tooltip: "", nextQuestion: 7 }, { tooltip: "", nextQuestion: 7 }, { tooltip: "", nextQuestion: 7 }, { tooltip: "", nextQuestion: 7 }, { tooltip: "", nextQuestion: 14 }] }, 7: { title: "Title", options: [{ tooltip: "", nextQuestion: 17 }, { tooltip: "", nextQuestion: 17 }, { tooltip: "", nextQuestion: 17 }, { tooltip: "", nextQuestion: 17 }, { tooltip: "", nextQuestion: 17 }] }, 8: { title: "Title", options: [{ tooltip: "", nextQuestion: 9 }, { tooltip: "", nextQuestion: 9 }, { tooltip: "", nextQuestion: 9 }] }, 9: { title: "Title", options: [{ tooltip: "", nextQuestion: 10 }, { tooltip: "", nextQuestion: 10 }, { tooltip: "", nextQuestion: 10 }] }, 10: { title: "Title", options: [{ tooltip: "", nextQuestion: 11 }, { value: "Roof", attribute: "Flue Exit", tooltip: "", nextQuestion: 15 }] }, 11: { title: "Title", options: [{ tooltip: "", nextQuestion: 12 }, { tooltip: "", nextQuestion: 12 }] }, 12: { finalQuestion: true, input: true, placeHolder: 'e.g SWS' }, 13: { title: "Title", options: [{ tooltip: "", nextQuestion: 6 }, { tooltip: "", nextQuestion: 6 }] }, 14: { title: "Title", options: [{ tooltip: "", nextQuestion: 7 }, { tooltip: "", nextQuestion: 7 }, { tooltip: "", nextQuestion: 10000 }] }, 15: { title: "Title", options: [{ tooltip: "", nextQuestion: 12 }, { tooltip: "", nextQuestion: 12 }] }, 17: { title: "Title", options: [{ tooltip: "", nextQuestion: 8 }, { tooltip: "", nextQuestion: 8 }, { tooltip: "", nextQuestion: 8 }, { tooltip: "", nextQuestion: 8 }, { tooltip: "", nextQuestion: 8 }] }, 10000: { isError: true, title: "Finally, what is the first part of your postcode?", error: "Postcode" } }
for (const path of paths(originalQuestions, 1))
console.log(path.join(" -> "))
.as-console-wrapper { min-height: 100%; }
1 -> 2 -> 3 -> 4 -> 13 -> 6 -> 7 -> 17 -> 8 -> 9 -> 10 -> 11 -> 12
1 -> 2 -> 3 -> 4 -> 13 -> 6 -> 7 -> 17 -> 8 -> 9 -> 10 -> 15 -> 12
1 -> 2 -> 3 -> 4 -> 13 -> 6 -> 14 -> 7 -> 17 -> 8 -> 9 -> 10 -> 11 -> 12
1 -> 2 -> 3 -> 4 -> 13 -> 6 -> 14 -> 7 -> 17 -> 8 -> 9 -> 10 -> 15 -> 12
1 -> 2 -> 3 -> 4 -> 13 -> 6 -> 14 -> 10000
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 17 -> 8 -> 9 -> 10 -> 11 -> 12
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 17 -> 8 -> 9 -> 10 -> 15 -> 12
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 14 -> 7 -> 17 -> 8 -> 9 -> 10 -> 11 -> 12
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 14 -> 7 -> 17 -> 8 -> 9 -> 10 -> 15 -> 12
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 14 -> 10000
1 -> 2 -> 3 -> 4 -> 5 -> 10000
1 -> 10000