admin管理员组

文章数量:1401444

I have a situation where I need to pare and find mon values over two arrays. I am clear on how to do it with one, but not sure how to do it in this case.

My first array looks like this:

[ { kind: 'E',
    path: [ 'short_name' ],
    lhs: 'testing',
    rhs: 'testing1' },
  { kind: 'E',
    path: [ 'agent_name' ],
    lhs: 'testing',
    rhs: 'testing2' } ]

The array above represents information pertaining to what changed on a document.

My second array looks like this:

[ { lhs: 'legacyId', rhs: 'id_number' },
  { lhs: 'name.short', rhs: 'short_name' },
  { lhs: 'name.long', rhs: 'agent_name' },
  { lhs: 'gender', rhs: 'gender' },
  { lhs: 'dob', rhs: 'date_of_birth' } ]

What I need to do is loop through and find mon values for "path" in the first array's elements, and the second array's "rhs" value.

So according to my examples here, I should end up with these values being found: short_name and agent_name.

How could I write a loop to do this over the two arrays?

I have a situation where I need to pare and find mon values over two arrays. I am clear on how to do it with one, but not sure how to do it in this case.

My first array looks like this:

[ { kind: 'E',
    path: [ 'short_name' ],
    lhs: 'testing',
    rhs: 'testing1' },
  { kind: 'E',
    path: [ 'agent_name' ],
    lhs: 'testing',
    rhs: 'testing2' } ]

The array above represents information pertaining to what changed on a document.

My second array looks like this:

[ { lhs: 'legacyId', rhs: 'id_number' },
  { lhs: 'name.short', rhs: 'short_name' },
  { lhs: 'name.long', rhs: 'agent_name' },
  { lhs: 'gender', rhs: 'gender' },
  { lhs: 'dob', rhs: 'date_of_birth' } ]

What I need to do is loop through and find mon values for "path" in the first array's elements, and the second array's "rhs" value.

So according to my examples here, I should end up with these values being found: short_name and agent_name.

How could I write a loop to do this over the two arrays?

Share Improve this question asked Jul 12, 2019 at 13:37 ReyRey 1,4332 gold badges17 silver badges32 bronze badges
Add a ment  | 

4 Answers 4

Reset to default 6

You can reduce the 1st array and use a forEach loop over the second array to see if each of the values are equal, then push the value to the accumulator:

const arr1 = [{ kind: 'E', path: [ 'short_name' ], lhs: 'testing', rhs: 'testing1' }, { kind: 'E', path: [ 'agent_name' ], lhs: 'testing', rhs: 'testing2' }]
const arr2 = [{ lhs: 'legacyId', rhs: 'id_number' }, { lhs: 'name.short', rhs: 'short_name' }, { lhs: 'name.long', rhs: 'agent_name' }, { lhs: 'gender', rhs: 'gender' }, { lhs: 'dob', rhs: 'date_of_birth' }]

const mon = arr1.reduce((a, o1) => {
  const match = arr2.find(o2 => o1.path[0] === o2.rhs)
  match && a.push(match.rhs)
  return a
}, [])

console.log(mon)

If you truly wanted to, you could write this in one line with a find instead of a second reduce:

const a = [{ kind: 'E', path: [ 'short_name' ], lhs: 'testing', rhs: 'testing1' }, { kind: 'E', path: [ 'agent_name' ], lhs: 'testing', rhs: 'testing2' }]
const b = [{ lhs: 'legacyId', rhs: 'id_number' }, { lhs: 'name.short', rhs: 'short_name' }, { lhs: 'name.long', rhs: 'agent_name' }, { lhs: 'gender', rhs: 'gender' }, { lhs: 'dob', rhs: 'date_of_birth' }]

const mon = a.reduce((a, o1) => (a.push(b.find(o2 => o1.path[0] === o2.rhs).rhs), a), [])

console.log(mon)

Or, for a more performant solution ;) You could use a set:

const a = [{ kind: 'E', path: [ 'short_name' ], lhs: 'testing', rhs: 'testing1' }, { kind: 'E', path: [ 'agent_name' ], lhs: 'testing', rhs: 'testing2' }]
const b = [{ lhs: 'legacyId', rhs: 'id_number' }, { lhs: 'name.short', rhs: 'short_name' }, { lhs: 'name.long', rhs: 'agent_name' }, { lhs: 'gender', rhs: 'gender' }, { lhs: 'dob', rhs: 'date_of_birth' }]
var monValues = []
var set = new Set([])

for (let i = 0; i < a.length; i++) { 
  const value = a[i].path[0]
  if (!set.has(value)) set.add(value)
}
for (let i = 0; i < b.length; i++) {
  const val = b[i].rhs
  if (set.has(val)) monValues.push(val)
}

console.log(monValues)

You can use a simply for inside a for...

This is the most simple (maybe not the most performatic) way you can do that, getting the value from first array, then looping the second one. If a value is found, then push it to another array (results) and break the second loop (there's no need to still running if a value already match).

var a = [ { kind: 'E',
    path: [ 'short_name' ],
    lhs: 'testing',
    rhs: 'testing1' },
  { kind: 'E',
    path: [ 'agent_name' ],
    lhs: 'testing',
    rhs: 'testing2' } ]


var b =[ { lhs: 'legacyId', rhs: 'id_number' },
  { lhs: 'name.short', rhs: 'short_name' },
  { lhs: 'name.long', rhs: 'agent_name' },
  { lhs: 'gender', rhs: 'gender' },
  { lhs: 'dob', rhs: 'date_of_birth' } ]
  
var results = [];  
for (var i = 0; i < a.length; i++){
  var path = a[i].path;
  
  for (var j = 0; j < b.length; j++){
    var rhs = b[j].rhs;
    if (rhs == path){
      results.push(b[j].rhs)
      break;
    }
    
  }
}

console.log(results)

You can do it in O(n^2) time by nesting a loop and searching through the second loop for every value of the first loop, or you can use a hashmap to do it in O(n) time. In JavaScript we use objects for that because their values can be accessed in O(1) time.

Example:

const array1 = [
  { kind: "E", path: ["short_name"], lhs: "testing", rhs: "testing1" },
  { kind: "E", path: ["agent_name"], lhs: "testing", rhs: "testing2" }
];

const array2 = [
  { lhs: "legacyId", rhs: "id_number" },
  { lhs: "name.short", rhs: "short_name" },
  { lhs: "name.long", rhs: "agent_name" },
  { lhs: "gender", rhs: "gender" },
  { lhs: "dob", rhs: "date_of_birth" }
];

const hashMap = {};
const monValues = [];

for (let i = 0; i < array1.length; i++) {
  const currentValue = array1[i].path[0];
  hashMap[currentValue] = true;
}

for (let i = 0; i < array2.length; i++) {
  const currentValue = array2[i].rhs;
  if (hashMap[currentValue]) monValues.push(currentValue);
}

//now monValues contains all of the mon between them. You may want to filter out duplicate matches, depends on your use case. 

While it may seem like a lot more code, the time plexity savings are huge as your data gets arbitrarily large by doing it this way. Imagine your data is 100 items long, already an O(n^2) solution would require 10,000 passes to find all of the matches. Conversely with the above solution, it would require 200 passes. These savings in time add up quickly as your data gets larger.

Make a Set out of the rhs values in second array and reduce first array and filter paths by checking against the set

const arr1= [ { kind: 'E',
    path: [ 'short_name' ],
    lhs: 'testing',
    rhs: 'testing1' },
  { kind: 'E',
    path: [ 'agent_name' ],
    lhs: 'testing',
    rhs: 'testing2' } ],
    
    arr2= [ { lhs: 'legacyId', rhs: 'id_number' },
  { lhs: 'name.short', rhs: 'short_name' },
  { lhs: 'name.long', rhs: 'agent_name' },
  { lhs: 'gender', rhs: 'gender' },
  { lhs: 'dob', rhs: 'date_of_birth' } ],
  
  arr2Set = new Set(arr2.map(({rhs}) => rhs)),
  matches = arr1.reduce((a,{path}) =>[...a, ...path.filter(p => arr2Set.has(p))],[]);
  
  
  console.log(matches)

本文标签: javascriptFinding Common Values While Looping Over Two ArraysStack Overflow