Home > Software design >  How to map and filter array of values based on value from another array in javascript?
How to map and filter array of values based on value from another array in javascript?

Time:07-21

Here I am having two arrays.

One array will hold the ids and another array holds the data. I want to map the values from the data by filtering with the value from the Id's array.

e.g: If 6 from the Ids array matches with data.id means I need to get the value inside the assets array. I have done that solution. But my solution seems quite complicated to understand.

const ids = [
    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
    6, 5, 4, 4, 4
  ];
  
  const data = [
    {
      id: 10,
      assets: [
        {
          type: 'First Section',
          value: 60
        },
        {
          type: 'Second Section',
          value: 40
        }
      ]
    },
    {
      id: 11,
      assets: [
        {
          type: 'First Section',
          value: 65
        },
        {
          type: 'Second Section',
          value: 35
        }
      ]
    },
    {
      id: 12,
      assets: [
        {
          type: 'First Section',
          value: 70
        },
        {
          type: 'Second Section',
          value: 30
        }
      ]
    },
    {
      id: 13,
      assets: [
        {
          type: 'First Section',
          value: 75
        },
        {
          type: 'Second Section',
          value: 25
        }
      ]
    },
    {
      id: 14,
      assets: [
        {
          type: 'First Section',
          value: 80
        },
        {
          type: 'Second Section',
          value: 20
        }
      ]
    },
    {
      id: 15,
      assets: [
        {
          type: 'First Section',
          value: 85
        },
        {
          type: 'Second Section',
          value: 15
        }
      ]
    },
    {
      id: 16,
      assets: [
        {
          type: 'First Section',
          value: 90
        },
        {
          type: 'Second Section',
          value: 10
        }
      ]
    },
    {
      id: 2,
      assets: [
        {
          type: 'First Section',
          value: 20
        },
        {
          type: 'Second Section',
          value: 80
        }
      ]
    },
    {
      id: 3,
      assets: [
        {
          type: 'First Section',
          value: 25
        },
        {
          type: 'Second Section',
          value: 75
        }
      ]
    },
    {
      id: 4,
      assets: [
        {
          type: 'First Section',
          value: 30
        },
        {
          type: 'Second Section',
          value: 70
        }
      ]
    },
    {
      id: 5,
      assets: [
        {
          type: 'First Section',
          value: 35
        },
        {
          type: 'Second Section',
          value: 65
        }
      ]
    },
    {
      id: 6,
      assets: [
        {
          type: 'First Section',
          value: 40
        },
        {
          type: 'Second Section',
          value: 60
        }
      ]
    },
    {
      id: 7,
      assets: [
        {
          type: 'First Section',
          value: 45
        },
        {
          type: 'Second Section',
          value: 55
        }
      ]
    },
    {
      id: 8,
      assets: [
        {
          type: 'First Section',
          value: 50
        },
        {
          type: 'Second Section',
          value: 50
        }
      ]
    },
    {
      id: 9,
      assets: [
        {
          type: 'First Section',
          value: 55
        },
        {
          type: 'Second Section',
          value: 45
        }
      ]
    },
    {
      id: 1,
      assets: [
        {
          type: 'First Section',
          value: 15
        },
        {
          type: 'Second Section',
          value: 85
        }
      ]
    }
  ];

Here I need to get only the first section value that is inside of the assets array.

I have done that by using the below code

 let res = ids.map((val) => data.filter(v => v.id === val)[0]).map(v => v.assets.filter(v => v.type === 'First Section')[0]).map(v => v.value)

console.log(res)

output

[
  40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
  40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
  40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
  40, 40, 40, 40, 35, 30, 30, 30
]

But is any way we can optimize the function furthermore. Please guide me on that

CodePudding user response:

You are right in sensing that your algorithm, although working, is incredibly inefficient. You are having to search through the entire data array for each item in the ids, which makes it an O(n^m) time complexity which will not scale well at all.

I think the best and most efficient way to do this would be to create a map of id -> first section value for each of your items in your data list. From there, it is a very simple and fast lookup to grab the section value for any of your IDs. It only requires 1 pass through the data array, and 1 pass through the ids array - O(n m), like so:

const ids = [
    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
    6, 5, 4, 4, 4
  ];
  
const data = [{"id":10,"assets":[{"type":"First Section","value":60},{"type":"Second Section","value":40}]},{"id":11,"assets":[{"type":"First Section","value":65},{"type":"Second Section","value":35}]},{"id":12,"assets":[{"type":"First Section","value":70},{"type":"Second Section","value":30}]},{"id":13,"assets":[{"type":"First Section","value":75},{"type":"Second Section","value":25}]},{"id":14,"assets":[{"type":"First Section","value":80},{"type":"Second Section","value":20}]},{"id":15,"assets":[{"type":"First Section","value":85},{"type":"Second Section","value":15}]},{"id":16,"assets":[{"type":"First Section","value":90},{"type":"Second Section","value":10}]},{"id":2,"assets":[{"type":"First Section","value":20},{"type":"Second Section","value":80}]},{"id":3,"assets":[{"type":"First Section","value":25},{"type":"Second Section","value":75}]},{"id":4,"assets":[{"type":"First Section","value":30},{"type":"Second Section","value":70}]},{"id":5,"assets":[{"type":"First Section","value":35},{"type":"Second Section","value":65}]},{"id":6,"assets":[{"type":"First Section","value":40},{"type":"Second Section","value":60}]},{"id":7,"assets":[{"type":"First Section","value":45},{"type":"Second Section","value":55}]},{"id":8,"assets":[{"type":"First Section","value":50},{"type":"Second Section","value":50}]}];

// for each item in data, map id to first section value for easy lookup
let sectionMap = data.reduce((res, curr) => {
  res[curr.id] = curr.assets.find(asset => asset.type === 'First Section').value;
  return res;
}, {});
console.log(sectionMap);

// map the id to its respective first section value with the lookup map we created
let result = ids.map(id => sectionMap[id]);
console.log(result);

  • Related