Write data from two arrays in one document - javascript

I have some data to be combined in one document in the mongoDB.
I have two arrays
const users = ['Anna', 'Jack', 'Paul', 'Elena']
const additionalData = ['data1', 'data2', 'data3', 'data4', 'data5']
for(const i of users){
const user = {
username: i.username
};
for(const key of additionalData){
user.keyword = key
}
await User.create(model)
}
[
{
username: 'Anna',
keyword: 'data1'
},
{
username: 'Jack',
keyword: 'data2'
},
{
username: 'Paul',
keyword: 'data3'
},
{
username: 'Elena',
keyword: 'data4'
}
]
I need to combine those arrays in the one document

Try this, You just need to loop through users and get data from additionalData with the current index. You can achieve this in 2 ways
Native Way
const users = ['Anna', 'Jack', 'Paul', 'Elena'];
const additionalData = ['data1', 'data2', 'data3', 'data4', 'data5'];
const newArray = [];
for (let i = 0; i < users.length; i += 1) {
const user = users[i];
const obj = { userName: user, keyword: additionalData[i] || null };
newArray.push(obj);
}
console.log(newArray);
ES6 Way
const users = ['Anna', 'Jack', 'Paul', 'Elena'];
const additionalData = ['data1', 'data2', 'data3', 'data4', 'data5'];
const result = users.map((r, i) => {
const obj = { userName: r, keyword: additionalData[i] || null };
return obj;
});
console.log(result)

// Users and additionalData array
const users = ['Anna', 'Jack', 'Paul', 'Elena'];
const additionalData = ['data1', 'data2', 'data3', 'data4', 'data5'];
// Merge them with this
$.merge( $.merge( [], users ), additionalData );

Related

filter array based on ObjectId

So I have 2 arrays here, let say
const users = [{_id:ObjectId("6274fb5b82bcc9b2ccc0a361"), name:p1, age:10},
{_id:ObjectId("6274fbc382bcc9b2ccc0a362"), name:p2, age:15},
{_id:ObjectId("6277a3d5b66c061096222bbd")}, name:p3, age:20];
const filterArray = [ObjectId("6274fbc382bcc9b2ccc0a362"),ObjectId("6277a3d5b66c061096222bbd")];
I want to filter result based on matching ObjectId, here's what I'm trying to do
const filteredUsers = users.filter(user=> !!filterArray.includes(user._id));
I'm expecting this result
filteredUsers = [{_id:ObjectId("6274fbc382bcc9b2ccc0a362"), name:p2, age:15},
{_id:ObjectId("6277a3d5b66c061096222bbd")}, name:p3, age:20]
Try to map the filterArray to an array of Strings and use that for comparison:
const filterArray = [ObjectId("6274fbc382bcc9b2ccc0a362"),ObjectId("6277a3d5b66c061096222bbd")];
const mappedFilterArray = filterArray.map(id => id.toString());
const filteredUsers = users.filter(user=> !!mappedFilterArray.includes(user._id.toString()));
You must convert it to string then filter it:
const users = [
{ _id: ObjectId('6274fb5b82bcc9b2ccc0a361'), name: 'p1', age: 10 },
{ _id: ObjectId('6274fbc382bcc9b2ccc0a362'), name: 'p2', age: 15 },
{ _id: ObjectId('6277a3d5b66c061096222bbd'), name: 'p3', age: 20 }
]
const filterArray = [
ObjectId('6274fbc382bcc9b2ccc0a362'),
ObjectId('6277a3d5b66c061096222bbd')
]
const stringFilterArray = filterArray.map(item => item.toString())
const filteredUsers = users.filter(user => stringFilterArray.includes(user._id.toString()))
/* result
[
{ _id:ObjectId("6274fbc382bcc9b2ccc0a362"), name:p2, age:15 },
{ _id:ObjectId("6277a3d5b66c061096222bbd"), name:p3, age:20 }
]
*/

How to change property name in array of objects in Javascript?

I have an array of objects -
const obj = [{name:'josh', city:'Sydney'},{name:'alice', city:'York'}]
I want to change 'city' property to 'town'. How can I make this change to the property of each object in the array?
Using Array#map:
const arr = [ { name: 'josh', city: 'Sydney' }, { name: 'alice', city: 'York' } ];
const res = arr.map(({ city, ...e }) => ({ ...e, town: city }));
console.log(res);
Using Array#forEach:
const arr = [ { name: 'josh', city: 'Sydney' }, { name: 'alice', city: 'York' } ];
arr.forEach(e => {
e.town = e.city;
delete e.city;
});
console.log(arr);
You can't do this directly, but what you can do is this:
const obj = [{name:'josh', city:'Sydney'},{name:'alice', city:'York'}]
for (let element of obj){
element.town = element.city;
delete element.city;
}

2 Array combine into one array javascript

Here is two array one is firstName another is lastName
{
firstName: ['name1', 'name2'],
lastName: ['last1', 'last2'],
}
but I want to formate the data into one array like this.
{
"name": [{
"firstName": "name1",
"lastName": "last1"
},
{
"firstName": "name2",
"lastName": "last2"
},
]
}
Using Array#map:
const getNameObj = (data = {}) => {
const { firstName = [], lastName = [] } = data;
if(firstName.length !== lastName.length) return;
const name = firstName.map((fn, i) => (
{ firstName: fn, lastName: lastName[i] }
));
return { name };
};
console.log(
getNameObj({ firstName: [ 'name1', 'name2' ], lastName: [ 'last1', 'last2' ] })
);
You could loop through it using for...in and push each element inside new array like this example
const data = {
firstName: [ 'name1', 'name2' ],
lastName: [ 'last1', 'last2' ],
}
let newData = [];
for (let el in data.firstName){
newData.push({
firstName: data.firstName[el],
lastName: data.lastName[el],
})
}
console.log(newData)
You can use Array.reduce to get the result.
const input = {
firstName: [ 'name1', 'name2' ],
lastName: [ 'last1', 'last2' ],
};
const result = input.firstName.reduce((acc, firstName, index) => {
acc.name.push({
firstName: firstName,
lastName: input.lastName[index]
})
return acc
}, {'name': []})
console.log(result);
You can build a new object {name: <value>}, and set your <value> to a mapped version of the firstName array, where each firstName from your array is mapped to an object of the form {firstName: ..., lastName: ...}. Here the firstName key has a value that is the current name, and the lastName key has a value from the lastName array at the corresponding index:
const obj = { firstName: ['name1', 'name2'], lastName: ['last1', 'last2'], };
const res = {
name: obj.firstName.map((firstName, i) => ({firstName, lastName: obj.lastName[i]}))
}
console.log(res);
here it is:
let obj = {firstName: ['name1', 'name2'],lastName: ['last1', 'last2']};
let finalObj = {};
finalObj.name = []
for (let i = 0; i < obj.firstName.length; i++)
finalObj.name.push(
{
firstName: obj.firstName[i],
lastName: obj.lastName[i]
}
)

How can we transform a nested array inside an object into one concatenated string value separated by commas?

I have the following sample array:
mainArray = [
{id: 15475, name: 'Ali', gender: 'Male', addresses: [
{address1: 'Lebanon'},
{address2: 'USA'}]
},
{id: 15475, name: 'Emily', gender: 'Female', addresses: [
{address1: 'UK'},
{address2: 'France'}]
},
];
I need to transform it into something like:
mainArray = [
{id: 15475, name: 'Ali', gender: 'Male', addresses: 'Lebanon, USA'},
{id: 15475, name: 'Emily', gender: 'Female', addresses: 'UK, France }
];
In this case, I added all nested arrays inside a an element of the mainArray into one single string value.
What I've done so far is, I extracted the key names of the mainArray:
extractedIndexes = ['id', 'name', 'gender', 'addresses'];
And made a loop to check the type of each element inside of the mainArray, and if it's an object I will concat the values of the nested array into one single string:
for (const idx of this.extractedIndexes) {
console.log(idx)
this.mainArray.forEach((elem) => {
let newItem = '';
if (typeof (elem[idx]) == 'object') {
elem[idx] = Object.keys(elem[idx]).forEach((key) => {
console.log(elem[idx][key])
// Add it to the field
})
console.log(elem[idx])
}
})
}
console.log(this.mainArray)
This line console.log(elem[idx][key]) is always returning the following:
{address1: "Lebanon"}
{address2: "USA"}
{address1: "UK"}
{address2: "France"}
Take note that here address1 and address2 are simple examples, as my real data contain multiple nested arrays, and each one have different new key names.
I tried to do the following:
if (typeof (elem[idx]) == 'object') {
elem[idx] = elem[idx].toString().split(',')
// Add it to the field
console.log(elem[idx])
}
But it returned [Object, Object].
So how can I transform a nested array into single concatenated string value?
Here is a stackblitz.
Just use map and use Object.values to get values from object:
mainArray.map(({addresses, ...rest}) => ({...rest, addresses:
addresses.map(s => Object.values(s)).join(', ')}) );
An example:
let mainArray = [
{id: 15475, name: 'Ali', gender: 'Male', addresses: [
{address1: 'Lebanon'},
{address2: 'USA'}]
},
{id: 15475, name: 'Emily', gender: 'Female', addresses: [
{address1: 'UK'},
{address2: 'France'}]
},
];
const result = mainArray.map(({addresses, ...rest}) => ({...rest, addresses: addresses.map(s => Object.values(s)).join(', ')}) );
console.log(result);
If you don't know whether the key is array, then you can try to use reduce method:
const result = mainArray.reduce((a, c)=> {
for (const key in c) {
if (Array.isArray(c[key]))
c[key] = c[key].map(s => Object.values(s)).join(', ');
}
a.push(c);
return a;
},[])
console.log(result);
An example:
let mainArray = [
{id: 15475, name: 'Ali', gender: 'Male', addresses: [
{address1: 'Lebanon'},
{address2: 'USA'}]
},
{id: 15475, name: 'Emily', gender: 'Female', addresses: [
{address1: 'UK'},
{address2: 'France'}]
},
];
const result = mainArray.reduce((a, c)=> {
for (const key in c) {
if (Array.isArray(c[key]))
c[key] = c[key].map(s => Object.values(s)).join(', ');
}
a.push(c);
return a;
},[])
console.log(result);
You could use recursive function to get addresses that will work on any nested structure and get the value if the key starts with address and value is not an object.
const data =[{"id":15475,"name":"Ali","gender":"Male","addresses":[{"address1":"Lebanon"},{"address2":"USA"}]},{"id":15475,"name":"Emily","gender":"Female","addresses":[{"address1":"UK"},{"address2":"France"}]}]
const flat = (data, prev = '') => {
let sep = prev ? ', ' : ''
let result = '';
for (let i in data) {
if (typeof data[i] == 'object') {
result += flat(data[i], prev + result)
} else if (i.startsWith('address')) {
result += sep + data[i]
}
}
return result
}
const result = data.map(({
addresses,
...rest
}) =>
({ ...rest,
addresses: flat(addresses)
}))
console.log(result)
{id: 15475, name: 'Ali', gender: 'Male', addresses: [
{address1: 'Lebanon'},
{address2: 'USA'}]
},
{id: 15475, name: 'Emily', gender: 'Female', addresses: [
{address1: 'UK'},
{address2: 'France'}]
},
];<br>
function toString(arro) {
return arro.reduce(
(acc, rec) => {
return [...acc, Object.values(rec)]
}, []
).join(',')
}
const res = mainArray.map(
it => {
return Object.keys(it).reduce(
(acc, item) => {
if (typeof it[item] === 'object') {
return {...acc, [item]: toString(it[item])}
}
return {...acc, [item]: it[item]}
}, {}
)
}
)```

Transform an array of data by status

I need to filter an array by property:
Here's the data, which I get from the server:
const mockResults = [
{
user: {
firstName: '1',
lastName: '1'
},
status: 'WRONG'
},
{
user: {
firstName: '2',
lastName: '2'
},
status: 'WRONG'
},
{
user: {
firstName: '3',
lastName: '3'
},
status: 'CORRECT'
}
];
To display the data, I need to transform it to a required by ReactNative SectionList format:
const requiredFormat = [
{
status: 'WRONG',
data: [{ user: {firstName: '1', lastName: '1'}}, { user: {firstName: '2', lastName: '2'}}],
},
{
status: 'CORRECT',
data: [{ user: {firstName: '3', lastName: '3'}}],
},
];
Basically, the mockResults should be sorted by status. There can be maximum of 4 statuses: correct, wrong, missed, chosen. All these statuses should include all the data marked with them.
What is the right way to implement this?
I've tried to filter the array, but I'm stuck at this point:
const transformArray = mockResults.filter(item => {
return {
answerStatus: item.status,
data: [item.user]
}
})
You may walk through the array (using Array.prototype.reduce() method) and create new element of resulting array once you see there's no such with current status or append current element data if one exists:
const mockResults = [{user:{firstName:'1',lastName:'1'},status:'WRONG'},{user:{firstName:'2',lastName:'2'},status:'WRONG'},{user:{firstName:'3',lastName:'3'},status:'CORRECT'}],
result = mockResults.reduce((r,{status, ...rest}) => {
const common = r.find(e => e.status == status)
common ?
common.data.push(rest) :
r.push({status, data:[rest]})
return r
}, [])
console.log(result)
.as-console-wrapper {min-height:100%}
You can use reduce() to achieve that:
const mockResults = [{user: { firstName: '1', lastName: '1'}, status: 'WRONG'},{user: {firstName: '2',lastName: '2'},status: 'WRONG'},{user: { firstName: '3',lastName: '3'},status: 'CORRECT'}];
const result = mockResults.reduce((a, {user, status}) => {
const temp = a.find(e => e.status === status);
if (temp) {
temp.data.push({user});
} else {
a.push({status, data: [{user}]});
}
return a;
}, []);
console.log(result);
Read from the Array.prototype.reduce() documentation:
The reduce() method executes a reducer function (that you provide) on each element of the array, resulting in a single output value.
I hope that helps!
You can reduce the array onto an object with its keys being the status property and its value an array of users with that status. Then, map over the entries to turn it back into an array of objects.
Note: The reduce function is creating a new object (accumulator) at each index. This is probably not practical for large data sets as it would be really slow.
const toSectionList = results =>
Object.entries(
results.reduce(
(obj, { user, status }) => ({
...obj,
[status]: [...(obj[status] || []), { user }],
}),
{}
)
).map(([status, data]) => ({ status, data }))
// example use:
const requiredFormat = toSectionList(mockResults)
The reduce function in this one modifies the accumulator object instead of creating a new one. It should preform better with larger data sets.
const toSectionList = results =>
Object.entries(
results.reduce((obj, { user, status }) => {
obj[status] = obj[status] || []
obj[status].push({ user })
return obj
}, {})
).map(([status, data]) => ({ status, data }))
That's what I did.
const mockResults = [
{
user: {
firstName: '1',
lastName: '1'
},
status: 'WRONG'
},
{
user: {
firstName: '2',
lastName: '2'
},
status: 'WRONG'
},
{
user: {
firstName: '3',
lastName: '3'
},
status: 'CORRECT'
}
]
function format(data) {
const resultDict = {}
for (let i of data) {
if (!resultDict[i.status]) {
resultDict[i.status] = { data: [] }
}
resultDict[i.status].data.push(i)
delete resultDict[i.status].data[resultDict[i.status].data.length - 1].status
}
const result = []
for (let i in resultDict) {
const res = {
status: i,
data: resultDict[i].data
}
result.push(res)
}
return result
}
console.log(format(mockResults))

Categories

Resources