-1

I have the following Javascript arrays:

ARRAY ONE:
[ TextRow { v_id: 3000 },
  TextRow { v_id: 3001 },
  TextRow { v_id: 3002 } ]

ARRAY TWO:
[ TextRow {
      s_id: 'S001',
      v_id: 3000,
      type: 'control' },
  TextRow {
      s_id: 'S002',
      v_id: 3001,
      type: 'mut' },
  TextRow {
      s_id: 'S003',
      v_id: 3001,
      type: 'mut' },
  TextRow {
      s_id: 'S005',
      v_id: 3001,
      type: 'control' },
  TextRow {
      s_id: 'S008',
      v_id: 3002,
      type: 'mut' } ]

For each element in Array One, I would like to get an array of all the elements in Array Two, where the v_id equals the v_id in array one. For example, for v_id = 3001, I would like to get all the elements in array two where the v_id = 3001 in a separate array. However, I am not sure what is the best way to do this task and whether Javascript already has some existing functions that can help me do this. I am asking this since my Array Two has over 1000 elements and I want to know if there is an efficient way to do this instead of just iterating through elements of the array with a nested for loop. Any insights are appreciated.

ceno980
  • 2,003
  • 1
  • 19
  • 37
  • 2
    have you tried something? – Kaushik Nov 14 '19 at 11:13
  • No, I am new to Javascript and arrays of this type. I know that you could iterate through the array with a nested for loop but my Array Two has over 1000 elements so I wanted to know if there is any efficient way to do this. – ceno980 Nov 14 '19 at 11:14
  • You could use `filter`. Check out this answer on how to filter objects in javascript : https://stackoverflow.com/a/5072145/2570277 – Nick Nov 14 '19 at 11:18

3 Answers3

1

You can do a .forEach (or .map) on ARRAY_ONE, then a .filter on ARRAY_TWO to get the matching elements.

I've added a getMatches function to make the logic a little more clear.

const ARRAY_ONE =
[  { v_id: 3000 },
   { v_id: 3001 },
   { v_id: 3002 } ];

const ARRAY_TWO =
[  {
      s_id: 'S001',
      v_id: 3000,
      type: 'control' },
   {
      s_id: 'S002',
      v_id: 3001,
      type: 'mut' },
   {
      s_id: 'S003',
      v_id: 3001,
      type: 'mut' },
   {
      s_id: 'S005',
      v_id: 3001,
      type: 'control' },
   {
      s_id: 'S008',
      v_id: 3002,
      type: 'mut' } ];
      
function getMatches(v_id, array) {
    return array.filter(el => el.v_id === v_id);
}

const result = ARRAY_ONE.map(v => { 
    return { array_one_id: v.v_id, matches: getMatches(v.v_id, ARRAY_TWO) };
});

console.log("Result:", result);
Terry Lennox
  • 29,471
  • 5
  • 28
  • 40
  • 1
    For the function in ARRAY_ONE.forEach, how is it known that v refers to ARRAY_ONE? Any insights are appreciated. – ceno980 Nov 14 '19 at 11:34
  • When we do a .map or forEach, the elements of the array are enumerated and each value is passed to the callback as the first argument. So v will be populated with each successive value of the array we're mapping. The index of each item will be passed as the second argument (if we need it!). See the docs here for more: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map – Terry Lennox Nov 14 '19 at 11:35
  • And when we call .map, we're passing each element of an array through the callback. So if we called .map(v => v * 2), we'd end up doubling each value in the array. – Terry Lennox Nov 14 '19 at 11:38
0

You can iterate over the first array with the .forEach( ) method.

Then, you can use the .filter( ) method on the array 2 as the callback function for the forEach.

you should have something like that:

arrayOne.forEach( elmArr1 => arrayTwo.filter( elmArr2 => elmArr1.v_id == elmArr2.v_id ) )
Levizar
  • 75
  • 1
  • 8
0

If you want to filter without grouping:

const firstArray =
[  { v_id: 3000 },
   { v_id: 3001 },
   { v_id: 3002 }
];

const secondArray =
[  {
      s_id: 'S001', v_id: 3000, type: 'control' },
   {
      s_id: 'S002', v_id: 3001, type: 'mut' },
   {
      s_id: 'S003', v_id: 3001, type: 'mut' },
   {
      s_id: 'S005', v_id: 3001, type: 'control' },
   {
      s_id: 'S008', v_id: 3002, type: 'mut' }
];    

const result = secondArray.filter(f=>
    firstArray.some(s=> s.v_id == f.v_id));

console.log(result);

If you want group items by key, then it can be done using reduce method:

const firstArray =
[  { v_id: 3000 },
   { v_id: 3001 },
   { v_id: 3002 }
];

const secondArray =
[  {
      s_id: 'S001', v_id: 3000, type: 'control' },
   {
      s_id: 'S002', v_id: 3001, type: 'mut' },
   {
      s_id: 'S003', v_id: 3001, type: 'mut' },
   {
      s_id: 'S005', v_id: 3001, type: 'control' },
   {
      s_id: 'S008', v_id: 3002, type: 'mut' }
];    

const keys = firstArray.reduce((a, {v_id}) => {
a[v_id] = a[v_id]  || 1;
return a;
}, {});

const allKeys = secondArray.reduce((a, {s_id, v_id, type}) => {
a[v_id] = a[v_id] || {values: []};
a[v_id].values.push({s_id, v_id, type});
return a;
}, {})

Object.keys(allKeys).forEach(k=>{
if( !keys.hasOwnProperty(k))
    delete allKeys[k];
})

console.log(allKeys);
StepUp
  • 36,391
  • 15
  • 88
  • 148