1

The array with objects:

var myArr = [ { user: 'jane', properties: ['prop1', 'prop2'] }
              { user: 'bob', properties: ['prop1', 'prop4'] }
              { user: 'dave', properties: ['prop1', 'prop2', 'prop3'] }
              { user: 'tim', properties: ['prop4', 'prop2', 'prop3'] } 
];

Is there a way in pure javascript or perhaps using lodash to obtain the users that have at least one property in common? The output should indicate which user matches with which user, without duplicates.

I've tried a number of things, but unfortunately was not able to get the desired output.

2
  • can you give a sample output? would it be an array or an object? Commented Oct 28, 2019 at 5:27
  • @Jayce444 Any output is good enough, as long as the output shows which users match with which users (matching pairs). The precise structure does not matter. Commented Oct 28, 2019 at 6:12

2 Answers 2

3

The solution below uses a Set to determine whether matching properties exist, combined with a reduce() operation to output matching user pairs:

const array = [{ user: 'jane', properties: ['prop1', 'prop2'] },
  { user: 'bob', properties: ['prop1', 'prop4'] },
  { user: 'dave', properties: ['prop1', 'prop2', 'prop3'] },
  { user: 'tim', properties: ['prop4', 'prop2', 'prop3'] }];
  
const result = array.reduce((acc, val1, i, arr) => [
  ...acc,
  ...arr.slice(i + 1).filter(val2 => {
    const properties = [...val1.properties, ...val2.properties];
    return new Set(properties).size < properties.length;
  }).map(val2 => [val1.user, val2.user])
], []);

console.log(result);

Sign up to request clarification or add additional context in comments.

1 Comment

This is precisely what I was looking for. I hadn't considered this approach. Thank you @Robby Cornelissen
0

You can use Map and Object, count the user occurrence for each properties, if it is same as length of array then there is atleast one property which occurs in all the users

let matcher = (arr) => {
  let mapper = {}
  arr.forEach(v => {
  let { user, properties } = v
    properties.forEach(v => {
      if (mapper[v]) {
        mapper[v].set(user, (mapper[v].get(user) || 0) + 1)
      } else {
        mapper[v] = new Map()
        mapper[v].set(user, 1)
      }
    })
  })
  return Object.entries(mapper).some(([_, v]) => {
    let total = [...v].reduce((a, [_, b]) => a + b, 0)
    return total === arr.length
  })
}

let arr = [{user: 'jane',properties: ['prop1', 'prop2']}, {user: 'bob',properties: ['prop1', 'prop4']}, {user: 'dave',properties: ['prop1', 'prop2', 'prop3']}, {user: 'tim',properties: ['prop4', 'prop2', 'prop3']}];

console.log(matcher(arr))

let arr2 = [{user: 'jane',properties: ['prop1', 'prop2']},{user: 'bob',properties: ['prop1', 'prop4']}]

console.log(matcher(arr2))

2 Comments

This does not answer this question, as it is of particular importance to know which users match with which users.
Some can be replaced with filter and you will get the prop which is common along all the users

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.