简体   繁体   中英

How to properly return string in forEach loop and if statement?

I've been on a project, and I'm stuck with returning a string.

Now let me present you the code:

export const returnAsString = (
  test: Array<TestQuestionAndAnswer>
) => {
  test.forEach((response) => {
    const fetchQuestion = getQuestionBasedOnId(response.questionId)
    fetchQuestion?.question.responses.forEach((res) => {
      if (
        res.responseId == response.responseId &&
        fetchQuestion.question.id == response.questionId
      ) {
        return `
        Question: ${fetchQuestion.question.text},
        Response: ${res.text}
        `
      }
    })
  })
}

Now this function should do next: inputed test is an array containing objects with key value pairs: questionId: id, responseId: id . I'm finding the texts of both by sending questionId into one function, and returning it's text, and later on comparing it with id in the test array. Now I need to return the whole test in this form:

question: text, response: text
//new line
question: text, response: text
//new line
etc..

and i don't know how to do this. I'm getting the values but i can't get one whole string. When I console.log this function it returns undefined, but if i console.log any of these text, it's working but it's overwriting:

question 1,
response 1
//each line new output, overwriting old one
question 2,
response 2
question 3,
response 3
etc..

So my question is how to return one whole string? I'm expecting something like this:

question: question1, response: response1
question: question2, response: response2
question: question3, response: response3
...

But not string overwriting each other, just only one string. with multiple question/responses.

EDIT:

This is how I did returned value, but the problem is returning first undefined then values undefined value1 value2..

export const returnAsString = (
  test: Array<TestQuestionAndAnswer>
) => {
  let string: any
  test.forEach((response) => {
    const fetchQuestion = getQuestionBasedOnId(response.questionId)
    fetchQuestion?.question.responses.forEach((res) => {
      if (
        res.responseId == response.responseId &&
        fetchQuestion.question.id == response.questionId
      ) {
        string = string + `
        Question: ${fetchQuestion.question.text},
        Response: ${res.text}
        `
      }
    })
  })
  return string
}

Working with arrays works just fine, but i need to return a string.

export const returnAsString = (
  test: Array<TestQuestionAndAnswer>
) => {
  let arr = new Array();
  test.forEach((response) => {
    const fetchQuestion = getQuestionBasedOnId(response.questionId)
    fetchQuestion?.question.responses.forEach((res) => {
      if (
        res.responseId == response.responseId &&
        fetchQuestion.question.id == response.questionId
      ) {
        arr.push({
        Question: fetchQuestion.question.text,
        Response: res.text
        })
      }
    })
  })
  return arr
}

Array#forEach doesn't return anything, you should use other function here.

export const returnAsString = (test: Array<TestQuestionAndAnswer>) => {
  return test
    .flatMap((response) => {
      const fetchQuestion = getQuestionBasedOnId(response.questionId);

      return fetchQuestion?.question.responses
        .filter(
          (res) =>
            res.responseId == response.responseId &&
            fetchQuestion.question.id == response.questionId
        )
        .map(
          (res) => `
        Question: ${fetchQuestion.question.text},
        Response: ${res.text}
        `
        );
    })
    .join("\n");
};

Also, assuming that there is only one res in fetchQuestion?.question.responses that satisfies this condition: res.responseId == response.responseId && fetchQuestion.question.id == response.questionId , it can be simplified:

export const returnAsString = (test: Array<TestQuestionAndAnswer>) => {
  return test
    .map((response) => {
      const fetchQuestion = getQuestionBasedOnId(response.questionId);

      const matchingResponse = fetchQuestion?.question.responses.find(
        (res) =>
          res.responseId == response.responseId &&
          fetchQuestion.question.id == response.questionId
      );

      if (matchingResponse) {
        return `
        Question: ${fetchQuestion.question.text},
        Response: ${matchingResponse.text}
        `;
      }

      return "":
    })
    .join("\n");
};

forEach isn't for returning values. What you want instead is reduce which takes an initial object and then calls a function that get's the return value of previous call and next item as argument.

export const returnAsString = (test: Array<TestQuestionAndAnswer>) =>
    test.reduce((prev, response) => {
        const fetchQuestion = getQuestionBasedOnId(response.questionId);
        return (
            prev +
            fetchQuestion?.question.responses.reduce((prev, res) => {
                if (
                    res.responseId === response.responseId &&
                    fetchQuestion.question.id === response.questionId
                ) {
                    return `Question: ${fetchQuestion.question.text}, Response: ${res.text}\n`;
                }
                return '';
            }, '')
        );
    }, '');

This will provide the expected result but since we are dealing with strings you can simplify it a bit more with join .

export const returnAsString = (test: Array<TestQuestionAndAnswer>) =>
    test
        // Flat map the arrays of response strings to one array
        .flatMap(response => {
            const fetchQuestion = getQuestionBasedOnId(response.questionId);
            return (
                // Map responses to stirngs
                fetchQuestion?.question.responses.map(res =>
                    // Switched to ternary here
                    res.responseId === response.responseId &&
                    fetchQuestion.question.id === response.questionId
                        ? // Return one string if condition is met
                          `Question: ${fetchQuestion.question.text}, Response: ${res.text}`
                        : // Return empty string if not since we must always return something
                          '',
                ) ?? []
            );
        })
        // Filter out empty rows
        .filter(r => r)
        // Join with new lines
        .join('\n');

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM