Как глубоко сравнить / сопоставить объекты в массиве, основываясь на свойстве массива строк в каждом объекте? - PullRequest
1 голос
/ 28 октября 2019

Массив с объектами:

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

Есть ли способ в чистом javascript или, возможно, использование lodash для получения пользователей, у которых есть хотя бы одно общее свойство? Вывод должен указать, какой пользователь соответствует какому пользователю, без дубликатов.

Я пробовал несколько вещей, но, к сожалению, не смог получить желаемый результат.

Ответы [ 2 ]

2 голосов
/ 28 октября 2019

В приведенном ниже решении используется Set для определения наличия соответствующих свойств в сочетании с операцией reduce() для вывода соответствующих пар пользователей:

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);
0 голосов
/ 28 октября 2019

Вы можете использовать Карту и Объект, подсчитать вхождение пользователя для каждого свойства, если оно равно длине массива, тогда есть хотя бы одно свойство, которое встречается у всех пользователей

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))
...