1

I have 3 sets of objects, 1 Set can be map to a corresponding set by a unique key. That same set can be mapped to the 3rd set by a different key. I need to be able to map all of these into a new combined set. These sets all have different properties.

Unique Count [users][sector]
Many Count [invoices]

Each unique [user] belongs to a specific [sector] found by (comitID), that same [user] can have many [invoices] though. A one to many field if your familiar with Relational Databases

const users= [ // Unique Entries
    {name:'user1', comitId: 'aa1'},
    {name:'user2', comitId: 'aa2'}
]

const sector= [ // Unique Entries
    {comitID: 'aa1', department: 'finance'},
    {comitID: 'aa2', department: 'marketing'},
    {comitID: 'aa3', department: 'engineering'}
]

const invoices= [ // Multiple Entries
    {name: 'user1' : statementDate: '2/1/2019'},
    {name: 'user1' : statementDate: '2/14/2019'},
    {name: 'user2' : statementDate: '2/1/2019'}
]

The new set should look like this. Cannot contain a list for the statement dates, they each need to be a new object.

const results = [
    {name: 'user1', comitId: 'aa1', department: 'finance', statementDate: '2/1/2019'},
    {name: 'user1', comitId: 'aa1', department: 'finance', statementDate: '2/14/2019'},
    {name: 'user2', comitId: 'aa2', department: 'marketing', statementDate: '2/1/2019'}
]

I have been trying this in Excel with vlookups and formulas. These files tend to be 10k for the unique counts and up 40k for the invoices.

halfer
  • 19,824
  • 17
  • 99
  • 186
xchrisbradley
  • 416
  • 6
  • 21
  • do you have anything you have tried? This really does look like something you would solve in excel or sql. – SpeedOfRound Mar 08 '19 at 20:22
  • Here's a similar question that might help: [Analog to SQL 'JOIN' for Javascript objects?](https://stackoverflow.com/questions/22593515/analog-to-sql-join-for-javascript-objects) – nireno Mar 08 '19 at 22:21

5 Answers5

1

You can use Array.map() over invoices and Array.find() to get the corresponding entries in users and then sectors:

const users = [ // Unique Entries
  {name:'user1', comitId: 'aa1'},
  {name:'user2', comitId: 'aa2'}
];

const sectors = [ // Unique Entries
  {comitID: 'aa1', department: 'finance'},
  {comitID: 'aa2', department: 'marketing'},
  {comitID: 'aa3', department: 'engineering'}
];

const invoices = [ // Multiple Entries
  {name: 'user1', statementDate: '2/1/2019'},
  {name: 'user1', statementDate: '2/14/2019'},
  {name: 'user2', statementDate: '2/1/2019'}
];

const result = invoices.map(invoice => {
  const user = users.find(u => u.name === invoice.name) || {};
  const sector = sectors.find(s => s.comitID === user.comitId) || {};
  return { ...invoice, ...sector };
});

console.log(result);
jo_va
  • 13,504
  • 3
  • 23
  • 47
0

I would suggest that you just iterate over the invoices and enrich the entries with the ones from the sets with unique entries.

Something like this (does not tested the code, but I hope you can understand the idea)

const data = invoices
    .map(entry => {...entry, ...{
        users.find(user => user.name === entry.name)
            .map(user => {...user,
                sector.find(sec=> sec.comitID === user.commitID)
             })
        }}
     )

You could improve speed when you first create a map out of the sets and then just lookup the join attributes instead of searching for them

const userMap = users.reduce((map, user) => {...map, ...{user.name: user}}, {})
const sectorMap = sector.reduce((map, sec) => {...map, ...{sector.comitID: sec}}), {})

const data = invoices.map(invoice => {...invoice, ...userMap[invoice.name], ...sector[userMap[invoice.name].comitID]})
thopaw
  • 3,796
  • 2
  • 17
  • 24
0

You could move user and sector items into a map and take this object, if necessary.

const
    users = [{ name: 'user1', comitId: 'aa1' }, { name: 'user2', comitId: 'aa2' }],
    sector = [{ comitID: 'aa1', department: 'finance' }, { comitID: 'aa2', department: 'marketing' }, { comitID: 'aa3', department: 'engineering' }],
    invoices = [{ name: 'user1', statementDate: '2/1/2019'}, { name: 'user1', statementDate: '2/14/2019' }, { name: 'user2', statementDate: '2/1/2019' }],
    setMap = k => (m, o) => m.set(o[k], o),
    userMap = users.reduce(setMap('name'), new Map),
    sectorMap = sector.reduce(setMap('comitID'), new Map),
    result = invoices.map(({ name, statementDate }) => {
        var { comitId } = userMap.get(name),
            { department } = sectorMap.get(comitId);
        return { name, comitId, department, statementDate };
    });

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

Here's a basic script that could work.

const users = [ // Unique Entries
    {name:'user1', comitId: 'aa1'},
    {name:'user2', comitId: 'aa2'}
]

const sectors = [ // Unique Entries
    {comitID: 'aa1', department: 'finance'},
    {comitID: 'aa2', department: 'marketing'},
    {comitID: 'aa3', department: 'engineering'}
]

const invoices = [ // Multiple Entries
    {name: 'user1', statementDate: '2/1/2019'},
    {name: 'user1', statementDate: '2/14/2019'},
    {name: 'user2', statementDate: '2/1/2019'}
]

sectors.forEach(sector => {
    const user = users.find(user => sector.comitID === user.comitId);
    if (user) {
        user.department = sector.department;
    }
});

const results = invoices.map(invoice => {
    const user = users.find(user => invoice.name === user.name);
    return Object.assign({}, user, { statementDate: invoice.statementDate });
});

console.log(results);
0

You can use map & filter

const users = [ // Unique Entries
  {
    name: 'user1',
    comitId: 'aa1'
  },
  {
    name: 'user2',
    comitId: 'aa2'
  }
]

const sector = [ // Unique Entries
  {
    comitID: 'aa1',
    department: 'finance'
  },
  {
    comitID: 'aa2',
    department: 'marketing'
  },
  {
    comitID: 'aa3',
    department: 'engineering'
  }
]

const invoices = [ // Multiple Entries
  {
    name: 'user1',
    statementDate: '2/1/2019'
  },
  {
    name: 'user1',
    statementDate: '2/14/2019'
  },
  {
    name: 'user2',
    statementDate: '2/1/2019'
  }
]
let newArray = invoices.map(function(item) {
  // this value will be use to find match between users & sectors
  let cId = users.filter(user => user.name === item.name)[0].comitId;
  return {
    name: item.name,
    statementDate: item.statementDate,
    comitId: cId,
    department: sector.filter(sector => sector.comitID === cId)[0].department
  }
});

console.log(newArray)
brk
  • 48,835
  • 10
  • 56
  • 78