I have a list of objects in an array. Each object has an email.
The array could have duplicate emails and I want to keep them.
I want to give a number let's say 4 and it should split the emails into groups of 4 emails into a map where the key is like group-1 ... and the value 4 unique emails in each key in this case I will have a map of 5 keys
const emails = [
{
userId: 'someuserid',
email: '[email protected]',
password: 'password1',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password1',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password10',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password10',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password2',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password2',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password3',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password3',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password4',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password4',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password5',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password5',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password6',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password6',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password7',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password7',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password8',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password8',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password9',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password9',
recovery: '[email protected]'
}
]
//this is the code i came up with but it's working
const groupsMap = new Map()
let sequence = 0
let profilePrefix = 'none'
let pivotPrefix = 0
for (let index = 0; index < emails.length; index ) {
const currentEmail = emails[index]?.email
const prevEmail = emails[index - 1]?.email
if (prevEmail && currentEmail === prevEmail) {
if (
profilesMap.has(`${prefix}-${pivotPrefix}`) &&
profilesMap.get(`${prefix}-${pivotPrefix}`).length < mailboxProfileNum &&
profilesMap
.get(`${prefix}-${pivotPrefix}`)
.findIndex((email) => currentEmail === email.email) === -1
) {
profilesMap.get(`${prefix}-${pivotPrefix}`).push(emails[index])
if (
profilesMap.get(`${prefix}-${pivotPrefix}`).length === mailboxProfileNum
) {
pivotPrefix
}
} else {
if (pivotPrefix > 0) {
const nextPivot = pivotPrefix
profilesMap.get(`${prefix}-${nextPivot}`).push(emails[index])
}
sequence
profilePrefix = `${prefix}-${sequence}`
profilesMap.set(profilePrefix, [emails[index]])
}
} else {
if (profilesMap.has(`${prefix}-${pivotPrefix}`)) {
if (
profilesMap.get(`${prefix}-${pivotPrefix}`).length < mailboxProfileNum
) {
profilesMap.get(`${prefix}-${pivotPrefix}`).push(emails[index])
if (
profilesMap.get(`${prefix}-${pivotPrefix}`).length ===
mailboxProfileNum
) {
pivotPrefix
}
} else {
sequence
profilesMap.set(`${prefix}-${sequence}`, [emails[index]])
}
} else {
sequence
pivotPrefix = sequence
profilePrefix = `${prefix}-${pivotPrefix}`
profilesMap.set(profilePrefix, [emails[index]])
}
}
}
Map(5) {
'group-1' => [
{
userId: 'userid',
email: '[email protected]',
password: 'password1',
recovery: '[email protected]'
},
{
userId: 'userid',
email: '[email protected]',
password: 'password2',
recovery: '[email protected]'
},
{
userId: 'userid',
email: '[email protected]',
password: 'password3',
recovery: '[email protected]'
},
{
userId: 'userid',
email: '[email protected]',
password: 'password4',
recovery: '[email protected]'
}
],
'group-2' => [
{
userId: 'userid',
email: '[email protected]',
password: 'password1',
recovery: '[email protected]'
},
{
userId: 'userid',
email: '[email protected]',
password: 'password2',
recovery: '[email protected]'
},
{
userId: 'userid',
email: '[email protected]',
password: 'password3',
recovery: '[email protected]'
},
{
userId: 'userid',
email: '[email protected]',
password: 'password4',
recovery: '[email protected]'
}
],
...
}
CodePudding user response:
You can save the groups as "buckets", and find the next bucket to put the email in. If no buckets have available spots, create a new bucket with the email.
const emails=[{userId:'someuserid',email:'[email protected]',password:'password1',recovery:'[email protected]'},{userId:'someuserid',email:'[email protected]',password:'password1',recovery:'[email protected]'},{userId:'someuserid',email:'[email protected]',password:'password10',recovery:'[email protected]'},{userId:'someuserid',email:'[email protected]',password:'password10',recovery:'[email protected]'},{userId:'someuserid',email:'[email protected]',password:'password2',recovery:'[email protected]'},{userId:'someuserid',email:'[email protected]',password:'password2',recovery:'[email protected]'},{userId:'someuserid',email:'[email protected]',password:'password3',recovery:'[email protected]'},{userId:'someuserid',email:'[email protected]',password:'password3',recovery:'[email protected]'},{userId:'someuserid',email:'[email protected]',password:'password4',recovery:'[email protected]'},{userId:'someuserid',email:'[email protected]',password:'password4',recovery:'[email protected]'},{userId:'someuserid',email:'[email protected]',password:'password5',recovery:'[email protected]'},{userId:'someuserid',email:'[email protected]',password:'password5',recovery:'[email protected]'},{userId:'someuserid',email:'[email protected]',password:'password6',recovery:'[email protected]'},{userId:'someuserid',email:'[email protected]',password:'password6',recovery:'[email protected]'},{userId:'someuserid',email:'[email protected]',password:'password7',recovery:'[email protected]'},{userId:'someuserid',email:'[email protected]',password:'password7',recovery:'[email protected]'},{userId:'someuserid',email:'[email protected]',password:'password8',recovery:'[email protected]'},{userId:'someuserid',email:'[email protected]',password:'password8',recovery:'[email protected]'},{userId:'someuserid',email:'[email protected]',password:'password9',recovery:'[email protected]'},{userId:'someuserid',email:'[email protected]',password:'password9',recovery:'[email protected]'}]
const buckets = [];
const bucketSize = 4;
emails.forEach((e) => {
const bucketIndex = buckets
.map((b, i) => [b, i]) // zip with index
.filter(([b]) => b.length < bucketSize) // buckets that aren't full
.find(([b]) => b.every((u) => u.email !== e.email)); // bucket with available spot
if (bucketIndex === undefined) buckets.push([e]); // create new bucket
else buckets[bucketIndex[1]].push(e); // push to existing bucket by index
});
// zip with keys and create map
const map = new Map(buckets.map((b, i) => [`group-${i}`, b]));
// Just for display - Maps aren't displayed properly in the output yet
console.log(Object.fromEntries(Array.from(map)));
.as-console-wrapper { max-height: 100% !important }
CodePudding user response:
Not sure But if you want group of unique emails than this will give you 4 object with unique emails.
- First I am filtering array with unique values of email and than using
chunk
function, that takes two parameter one the array and second the size of array. - The procedure of chunk function is as below, the only thing **missing here is key otherwise you are getting 4 email object of array in chunks.
- Take an empty array to push array chuncks
- check if we will have extra chunks or not;
- if array length's moudle with chunk size is not equal to zero that we have to count the number of rounds
- if array length's moudle with chunk size is zero than we just need to push array.splice(0,size) till the array size is not equals to zero
- if we have rounds , than we just need to push array till the rounds are not complete once its compelete we just need to add extra to result by arra.push(0,extra);
- In other words,push chunks in array till our array's length is not equal to extra and once array length is just as extra add remaining by arra.push(0,extra);
const emails = [{
userId: 'someuserid',
email: '[email protected]',
password: 'password1',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password1',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password10',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password10',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password2',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password2',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password3',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password3',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password4',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password4',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password5',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password5',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password6',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password6',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password7',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password7',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password8',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password8',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password9',
recovery: '[email protected]'
},
{
userId: 'someuserid',
email: '[email protected]',
password: 'password9',
recovery: '[email protected]'
}
];
let filterdResult = []; // to store unique email objects
// to filter emails object with unique email
let filterArray = emails.reduce((visitedEmailContainer, currentEmail) => {
if (!visitedEmailContainer.includes(currentEmail.email)) {
filterdResult.push(currentEmail);
visitedEmailContainer.push(currentEmail.email);
return visitedEmailContainer;
}
return visitedEmailContainer;
}, []);
function chunk(array, size) {
/*
- Take an empty array to push array chuncks
- check if we will have extra chunks or not;
- if array length's moudle with chunk size is not equal to zero that we have to count the number of rounds
- if array length's moudle with chunk size is zero than we just need to push array.splice(0,size) till the array size is not equals to zero
- if we have rounds , than we just need to push array till the rounds are not complete once its compelete we just need to add extra to result by arra.push(0,extra);
- In other words,push chunks in array till our array's length is not equal to extra and once array length is just as extra add remaining by arra.push(0,extra);
*/
let result = [];
let extra = array.length % size;
if (extra == 0) {
while (array.length !== 0) {
result.push(array.splice(0, size));
}
} else if (extra) {
while (array.length != extra) {
result.push(array.splice(0, size));
}
result.push(array.splice(0, extra));
}
console.log(result);
return result;
}
chunk(filterdResult, 4);