I have the following arrays:
const primary = [ {recordId:123, type: "Primary" }, {recordId:123, type: "Primary" }, {recordId:123, type: "Primary" }, {recordId:9393, type: "Primary" }, {recordId:9393, type: "Primary" }, {recordId:9393, type: "Primary" }, ]; const secondary = [ {recordId:123, type: "Secondary" }, {recordId:123, type: "Secondary" }, {recordId:9393, type: "Secondary" }, {recordId:9393, type: "Secondary" }, {recordId:9393, type: "Secondary" }, ];
So I want to display a list of recordIds where we don’t have an equal number of records in either array for given recordId.
e.g In above example recordId:123
has 3 x records in primary array but only 2 x in the secondary array, therefore because the number of records don’t match up for this Id
I want to be able to report on this recordId.
I’ve had a go and this is what solution I’ve produced so far using vanilla Javascript:
const missingRecords = [] const primaryOccurences = primary.reduce((acc, val) => acc.set(val.recordId, 1 + (acc.get(val.recordId) || 0)), new Map()); const secondaryOccurences = secondary.reduce((acc, val) => acc.set(val.recordId, 1 + (acc.get(val.recordId) || 0)), new Map()); console.log(primaryOccurences); console.log(secondaryOccurences); primaryOccurences.forEach((value,key)=> { for (const[skey, svalue] of secondaryOccurences.entries()) { if(skey === key && value !== svalue) { missingRecords.push(key); } } }) console.log(missingRecords);
const primary = [{ recordId: 123, type: "Primary" }, { recordId: 123, type: "Primary" }, { recordId: 123, type: "Primary" }, { recordId: 9393, type: "Primary" }, { recordId: 9393, type: "Primary" }, { recordId: 9393, type: "Primary" }, ]; const secondary = [{ recordId: 123, type: "Secondary" }, { recordId: 123, type: "Secondary" }, { recordId: 9393, type: "Secondary" }, { recordId: 9393, type: "Secondary" }, { recordId: 9393, type: "Secondary" }, ]; const missingRecords = [] const primaryOccurences = primary.reduce((acc, val) => acc.set(val.recordId, 1 + (acc.get(val.recordId) || 0)), new Map()); const secondaryOccurences = secondary.reduce((acc, val) => acc.set(val.recordId, 1 + (acc.get(val.recordId) || 0)), new Map()); console.log(primaryOccurences); console.log(secondaryOccurences); primaryOccurences.forEach((value, key) => { for (const [skey, svalue] of secondaryOccurences.entries()) { if (skey === key && value !== svalue) { missingRecords.push(key); } } }) console.log(missingRecords);
Running this code produces the following:
[123]
So is there a better alternative to the above from a performance standpoint? I’m open to other ideas / suggestions.
Advertisement
Answer
You can use only one map. Will be better for big arrays.
It require only one loop. And you can detect if there are more records in the primary
( > 0
) or in the secondary
( < 0
)
Also you can rewrite reduce
in for
notation but it make sense only for large arrays
https://measurethat.net/Benchmarks/Show/19290/0/so-two-map-compare
const primary = [ {recordId:123, type: "Primary" }, {recordId:123, type: "Primary" }, {recordId:123, type: "Primary" }, {recordId:9393, type: "Primary" }, {recordId:9393, type: "Primary" }, {recordId:9393, type: "Primary" }, ]; const secondary = [ {recordId:123, type: "Secondary" }, {recordId:123, type: "Secondary" }, {recordId:9393, type: "Secondary" }, {recordId:9393, type: "Secondary" }, {recordId:9393, type: "Secondary" }, ]; const missingRecords = [] const occurences = primary.reduce((acc, val) => acc.set(val.recordId, 1 + (acc.get(val.recordId) || 0)), new Map()); secondary.reduce((acc, val) => acc.set(val.recordId, (acc.get(val.recordId) || 0) - 1), occurences); for (const [skey, svalue] of occurences.entries()) { if (svalue !== 0) { missingRecords.push(skey); } } console.log(missingRecords);