Вот еще одно предложение маршрута, по которому вы могли бы пойти.Идея состоит в том, чтобы использовать один Array.reduce
для группировки по id
и сохранить все значения (vls
) и объединенные результаты (ids
) в этом accumulator object
,
Таким образом, вы можете легко сравнить name/phone/email
, используя Array.some
+ Array.includes
(которыйэто то, что делает функция getGroupId
).
После того как вы сгруппировали и получили почти окончательный результат, просто prettify
удалите группы с length
из одного и выберите только массив ids
из остальных:
var data = [ {id:1,name:'John',phone:'11111111',email:'aaaa@test.com'}, {id:2,name:'Marc',phone:'22222222',email:'bbbb@test.com'}, {id:3,name:'Ron',phone:'99999999',email:'aaaa@test.com'}, {id:4,name:'Andrew',phone:'55555555',email:'dddd@test.com'}, {id:5,name:'Wim',phone:'99999999',email:'gggg@test.com'}, {id:6,name:'Marc',phone:'33333333',email:'cccc@test.com'}, {id:7,name:'Dan',phone:'44444444',email:'cccc@test.com'} ];
const getGroupId = (obj, vals) => Object.entries(obj)
.find(([k,v]) => v.vls.some(x => vals.includes(x))) || []
const group = d => d.reduce((r, c) => {
let values = Object.values(c), groupID = getGroupId(r, values)[0]
if(!groupID)
r[c.id] = ({ vls: values, ids: [...r[c.id] || [], c.id] })
else {
r[groupID] = ({
vls: [...r[groupID].vls, ...values], ids: [...r[groupID].ids, c.id]
})
}
return r
}, {})
const prettify = grp => Object.values(grp).reduce((r,c) => {
if(c.ids.length > 1)
r.push(c.ids)
return r
}, [])
console.log(prettify(group(data)))
Стоит отметить, что нам не важно количество объектов, так как мы делаем Object.values
.Таким образом, вы можете легко добавить еще один address
или fax
в этот список, и он будет по-прежнему работать с zero code changes
.
. По отзывам, есть еще одна версия, которая работает немного по-другому:
var data = [ {id:1,name:'John',phone:'11111111',email:'aaaa@test.com'}, {id:2,name:'Marc',phone:'22222222',email:'bbbb@test.com'}, {id:3,name:'Ron',phone:'99999999',email:'aaaa@test.com'}, {id:4,name:'Andrew',phone:'55555555',email:'dddd@test.com'}, {id:5,name:'Wim',phone:'99999999',email:'gggg@test.com'}, {id:6,name:'Marc',phone:'33333333',email:'cccc@test.com'}, {id:7,name:'Dan',phone:'44444444',email:'cccc@test.com'} ];
var testData = [{ id: 1, name: 'John', phone: '1', email: 'a' }, { id: 2, name: 'Marc', phone: '2', email: 'b' }, { id: 3, name: 'Ron', phone: '1', email: 'b' }];
const getGroupId = (obj, vals) => Object.entries(obj)
.find(([k,v]) => v.vls.some(x => vals.includes(x))) || []
const group = d => d.reduce((r,c,i,a) => {
let values = Object.values(c), groupID = !i ? i : getGroupId(r, values)[0]
if (!groupID) {
let hits = a.filter(x =>
x.id != c.id && values.some(v => Object.values(x).includes(v)))
hits.forEach(h =>
r[c.id] = ({ vls: [...values, ...Object.values(h)], ids: [c.id, h.id] }))
}
else
r[groupID] = r[groupID].ids.includes(c.id) ? r[groupID] :
({ vls: [...r[groupID].vls, ...values], ids: [...r[groupID].ids, c.id] })
return r
}, {})
const prettify = grp => Object.values(grp).reduce((r, c) => {
if (c.ids.length > 1)
r.push(c.ids)
return r
}, [])
console.log(prettify(group(data))) // OP data
console.log(prettify(group(testData))) // Test data
Причиной этой версии является testData
, предоставленный @Mark
, у которого 2-й элемент не соответствует первому, но соответствует 3-му, который фактически соответствует 1-му... так что все они должны быть хитами.
Чтобы добраться до этого, как только мы найдем совпадение, мы ищем совпадения того же самого начального совпадения и нажимаем в той же группе, чтобы у нас было максимальное количество данных для сопоставления.
Результатом является то, что как только мы получим первую группу с первым элементом, мы найдем и нажмем также и третий, и оттуда намного легче сопоставить 2-й.Логика немного сложнее, и я бы сказал, менее производительно.