Search code examples
javascriptarraysdata-structureslookupreduce

How do i get desired result by comparing array of object with object in Javascript?


I have below sample data array of object and submittedValue object. The data array of object is constant it won't change but submitttedValue object will change as user proceed with the answer. I have put below desired result need to extract from data array of object and submittedValue object. Please help me out if you have any solution for this.

const data = [{
  id: "Q1",
  state: "Test 1",
  answers: [
    { id: "Q1A1", text: "Yes" },
    { id: "Q1A2", text: "No" },
  ],
}, {
  id: "Q2",
  state: "Test 2",
  answers: [
    { id: "Q2A1", text: "Yes" },
    { id: "Q2A2", text: "No" },
  ],
}];

const submittedValue = {
  Q1: {
    Q1A1: "Yes",
  },
  Q2: {
    Q2A2: "No",
  },
};

How do I get the below desired result by comparing above data array of object with submittedValue object ?

// Expected outcome

const result = [
  { state: "Test 1", answer: "Yes" },
  { state: "Test 2", answer: "No" },
];

Solution

  • From the provided data structure, ...

    const data = [{
      id: 'Q1',
      state: 'Test 1',
      answers: [
        { id: 'Q1A1', text: 'Yes' },
        { id: 'Q1A2', text: 'No' },
      ],
    }, {
      id: 'Q2',
      state: 'Test 2',
      answers: [
        { id: 'Q2A1', text: 'Yes' },
        { id: 'Q2A2', text: 'No' },
      ],
    }];
    

    ... the submitted value ...

    const submittedValue = {
      Q1: { Q1A1: 'Yes' },
      Q2: { Q2A2: 'No' },
    };
    

    ... and the expected result ...

    const result = [
      { state: 'Test 1', answer: 'Yes' },
      { state: 'Test 2', answer: 'No' },
    ];
    

    ... it is obvious that one needs the data just for looking up the test name which is a data-item's state-value and becomes a result-item's state-value as well ... const result = [ { state: 'Test 1', ... }, ... ];.

    As for any result-item's answer-value, it has to be extracted from each related submitted value's single nested property, because in the latter lays the truth and not within the data structure.

    Thus, in order to come up with the most efficient approach for retrieving any submitted value's test name, one does reduce the data array into an object-based lookup-table where one maps its state/test-name by its id where the latter is the key and the former is the value ... e.g. ...

    {
      Q1: 'Test 1',
      Q2: 'Test 2',
    }
    

    The final result then just needs to be mapped from the submittedValue's entries array, where each entry-key relates to the result's state/test-name value and each entry-value is an object with just a single own property. The property name does not matter for the result-item's answer-value will always be the first item of the object's values array.

    Thus an efficient solution can be based on a single reduce task for creating the lookup and another single map task which already creates the final result ...

    const data = [{
      id: 'Q1',
      state: 'Test 1',
      answers: [
        { id: 'Q1A1', text: 'Yes' },
        { id: 'Q1A2', text: 'No' },
      ],
    }, {
      id: 'Q2',
      state: 'Test 2',
      answers: [
        { id: 'Q2A1', text: 'Yes' },
        { id: 'Q2A2', text: 'No' },
      ],
    }];
    const submittedValue = {
      Q1: { Q1A1: 'Yes' },
      Q2: { Q2A2: 'No' },
    };
    
    // ... approach / solution ...
    
    const testNameLookup = data
      .reduce((lookup, testItem) => {
    
        const { id, state } = testItem;
        lookup[id] = state;
    
        return lookup;
      }, {});
    
    const result = Object
      .entries(submittedValue)
      .map(([ key, value ]) => {
    
        const state = testNameLookup[key];
        const answer = Object.values(value)[0];
    
        return { state, answer };
      });
    
    console.log({ result, testNameLookup });
    .as-console-wrapper { min-height: 100%!important; top: 0; }