I want to duplicate entire objects inside an array, based on the properties inside the object. I need to duplicate the objects, based on the split emails, in nominations.
For example
array = [
{
id:1,
name: ravi,
nominations: xyz#gmail.com, abc#gmail.com
},
{
id:2
name: ramu,
nominations: 123#gmail.com, 456#gmail.com
}
]
Need Output like
Output_array = [
{
id:1,
name: ravi,
nominations: xyz#gmail.com
},
{
id:1,
name: ravi,
nominations: abc#gmail.com
},
{
id:2
name: ramu,
nominations: 123#gmail.com
},
{
id:2
name: ramu,
nominations: 456#gmail.com
}
]
The easiest way would be to flatMap over the items, then map over the nominations.
const data = [{
id:1,
name: "ravi",
nominations: "xyz#gmail.com, abc#gmail.com"
},
{
id:2,
name: "ramu",
nominations: "123#gmail.com, 456#gmail.com"
}];
const result = data.flatMap(item => {
return item.nominations.split(", ").map(email => ({
id: item.id,
name: item.name,
nomination: email
}))
})
console.log(result)
A pretty straightforward way using loops:
let data = [
{
"id": 1,
"name": "ravi",
"nominations": "xyz#gmail.com,abc#gmail.com"
},
{
"id": 2,
"name": "ramu",
"nominations": "123#gmail.com,456#gmail.com"
}
];
let newData = []
for (let element of data) {
let emailIds = element.nominations.split(",");
if (emailIds.length > 1) {
for (let emailId of emailIds)
newData.push({ id: element.id, name: element.name, nominations: emailId })
}
}
console.log(newData)
Explanation: Starting with traversing the entire objects, in each object you split the nominations string and split it with "," to check if there is more than one email. If it does exist, you run a loop to individually add them.
This could be done with an arguably long one-liner. Object.assign function can be employed to duplicate input object while changing property/properties of interest.
let input = [{
id: 1,
name: `ravi`,
nominations: `xyz#gmail.com, abc#gmail.com`
},
{
id: 2,
name: `ramu`,
nominations: `123#gmail.com, 456#gmail.com`
}];
let output = input.flatMap(i => i.nominations.split(",").map(n => Object.assign({}, i, { nominations: n.trim() })));
console.log(output);
You can try this code:
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
var data_array = [
{
id:'1',
name: 'ravi',
nominations: 'xyz#gmail.com, abc#gmail.com',
},
{
id:'2',
name: 'ramu',
nominations: '123#gmail.com, 456#gmail.com',
},
];
var output_array = data_array.flatMap(key => {
return key.nominations.split(",").map(split_email => ({
id: key.id,
name: key.name,
nomination: $.trim(split_email)
}))
});
console.log(output_array);
});
</script>
</head>
<body>
</body>
</html>
Related
I have an array that looks something like this:
const arrayObj = [
{
id: 1,
itemsList: [
{
name: "Paul",
},
{
name: "Newman",
},
],
},
{
id: 2,
itemsList: [
{
name: "Jack",
},
{
name: "Man",
},
],
},
]
What I want is to filter the objects whose itemsList contain an object with the name of a certain value. For example, I want to be able to filter out an array with objects whose inner objects with names that contain "ul" (in this case the name Paul contains "ul"), it should give me an output as such:
const outputArray = [
{
id: 1,
itemsList: [
{
name: "Paul",
},
{
name: "Newman",
},
]
}
]
So far, I've only been able to filter out a simple flat array of objects with this function:
function filterByName(array: any, string: any) {
return array.filter((obj: any) =>
["name"].some((key: any) =>
String(obj[key]).toLowerCase().includes(string.toLowerCase())
)
);
}
but I don't know how to apply it to my case.
Here you can use the some method combined with the includes method
const arrayObj = [{
id: 1,
itemsList: [{
name: "Paul",
},
{
name: "Newman",
},
],
},
{
id: 2,
itemsList: [{
name: "Jack",
},
{
name: "Man",
},
],
},
]
const getFilterArray = (name) => {
return arrayObj.filter(obj => obj.itemsList.some(x => x.name.toLowerCase().includes(name.toLowerCase())))
}
console.log(getFilterArray("ul"))
const result = arrayObj.filter(({ itemsList }) =>
itemsList.some(({ name }) => name.toLowerCase().includes('ul')));
Can you try this?
I am trying to remove all the _er and _bx from the array, how can I do it? The way I tried doesn't seem to work. I'd like to see a solution where it removes all after _, and aswell only the letter that I put in for e.g remove all _ with er after.
const nullValue = {
collection: [{
name: "test_er"
},
{
name: "test_bx"
},
{
name: "fred"
},
{
name: "test_er"
}
]
};
const newArr = []
for (let [key, item] of nullValue.collection.entries()) {
item.name.replace(/_er/g, '')
newArr.push(item)
}
console.log(newArr)
Is this what you're looking for?
const nullValue = {
collection: [
{
name: 'test_er',
},
{
name: 'test_bx',
},
{
name: 'fred',
},
{
name: 'test_er',
},
],
};
nullValue.collection = [
...nullValue.collection.map(item => ({
name: item.name.replace(/_.*$/, ''),
})),
];
console.log(nullValue);
You can also use .split('_')[0] with the map method similar to Dmitry's answer... This gives you the first string of the split array, split at the underscore...
const nullValue = {
collection: [{
name: "test_er"
},
{
name: "test_bx"
},
{
name: "fred"
},
{
name: "test_er"
}
]
};
nullValue.collection = [ ...nullValue.collection.map( names => ({ name: names.name.split('_')[0], })),]
console.log(nullValue)
If you want to keep the original array of objects...
const nullValue = {
collection: [{
name: "test_er"
},
{
name: "test_bx"
},
{
name: "fred"
},
{
name: "test_er"
}
]
};
const newArr = { collection :
[ ...nullValue.collection.map( names =>
({ name: names.name.split('_')[0], })),
]}
console.log('newArr = ', newArr)
console.log('nullValue = ', nullValue)
You were VERY close with your original code, but the mistake was that String.replace() does not operate in-place, but rather returns its result. I've modified your code and added a comment below:
const nullValue = {
collection: [{
name: "test_er"
},
{
name: "test_bx"
},
{
name: "fred"
},
{
name: "test_er"
}
]
};
const newArr = []
for (let [key, item] of nullValue.collection.entries()) {
// My change is here
newArr.push( item.name.replace(/_er/g, '') )
}
console.log(newArr)
const nullValue = {
collection: [
{
name: "test_er"
},
{
name: "test_bx"
},
{
name: "fred"
},
{
name: "test_er"
}
]
};
nullValue.collection = nullValue.collection.map(i => i.name.replace(/_.*$/, ''))
console.log(nullValue)
This is preferable to .map() since you don't need a new array. You just want to change the strings:
const nullValue = {
collection: [
{ name: "test_er" },
{ name: "test_bx" },
{ name: "fred" },
{ name: "test_er" }
]
};
nullValue.collection.forEach(i => i.name = i.name.replace(/_.*$/, ''));
console.log(nullValue.collection);
I wonder how I can group this array based on the prefix text in name key (split the name key at the : colon) using Lodash.
const tags = [
{ name: 'Animals: Frogs', id: 1 },
{ name: 'Animals: Lions', id: 2 },
{ name: 'Birds: Crows', id: 3 }
];
to
const tags = [{
animals: [
{ name: 'Frogs', id: 1 },
{ name: 'Lions', id: 2 },
],
birds: [
{ name: 'Crows', id: 3}
]
}];
Does Lodash have any functions to handle this, or is a custom function/regex needed?
If the pure JS suffices, it can be done this way (the result is an object here, not an array, but this can be changed if needed):
const tags = [
{ name: 'Animals: Frogs', id: 1 },
{ name: 'Animals: Lions', id: 2 },
{ name: 'Birds: Crows', id: 3 }
];
const tags2 = tags.reduce(
(acc, { name, id }) => {
let [group, type] = name.split(': ');
group = group.toLowerCase();
acc[group] ??= [];
acc[group].push({ name: type, id });
return acc;
},
{},
);
console.log(tags2);
Okay it was a bit hard to explain what I want. Let me explain in more detail. I have an array of objects. Because the "only" identifier of the arrays elements are their indexes, if we want to change an element we need to know which is the target index. But even if we have the index, I don't want to change the whole object, just assign the new one and "merge" them together.
I have a solution, which is ugly, but at least makes more sense what I want:
const users = [
{
id: 0,
name: "John",
hobby: "soccer"
},
{
id: 1,
name: "Alice",
hobby: "squash"
},
{
id: 2,
name: "Greg",
hobby: "guitar"
}
]
const newUsers = [
{
id: 0,
work: "developer"
},
{
id: 2,
work: "musician"
},
{
id: 3,
name: "Roger",
work: "accountant"
}
]
const concatArray = (newArray, oldArray) => {
const objectFromArray = array => array.reduce((object, user) => {
object[user.id] = user;
return object
}, {});
const objectOfOldArray = objectFromArray(oldArray);
const objectOfNewArray = objectFromArray(newArray);
const allIds = Object.keys({...objectOfOldArray, ...objectOfNewArray})
return allIds.map(id => {
const oldProps = objectOfOldArray[id] || {};
const newProps = objectOfNewArray[id] || {};
return {id, ...oldProps, ...newProps}
})
}
console.log(concatArray(newUsers, users))
It works fine, but there should be a more sufficient solution for this. I mean it's a very small operation, adding some properties to the specified objects, but my solution is too over-complicated to earn this. There should be an easier way to earn this.
You can try below approach of Array.forEach
const users = [
{
id: 0,
name: "John",
hobby: "soccer"
},
{
id: 1,
name: "Alice",
hobby: "squash"
},
{
id: 2,
name: "Greg",
hobby: "guitar"
}
]
const newUsers = [
{
id: 0,
work: "developer"
},
{
id: 2,
work: "musician"
},
{
id: 3,
name: "Roger",
work: "accountant"
}
]
let updatedUsers = {};
[...users, ...newUsers].forEach(d => updatedUsers[d.id] = { ...(updatedUsers[d.id] || {}), ...d })
console.log(Object.values(updatedUsers))
I want to filter out a nested array of objects but stuck at the filter part.
How to remove one of the mark?
this.state = {
data: [
{
id: 1,
name: "Main",
subs: [
{
id: "jay",
name: "Jay",
mark: [
{
id: "5a5d84b94a074c49ef2d4553",
name: 100
},
{
id: "5a5d84b94a074119ef2d4553",
name: 70
}
]
}
]
}
]
};
https://codesandbox.io/s/p39momxzp7
I try to use es6 as it's more readable.
expected output
data: [
{
id: 1,
name: "Main",
subs: [
{
id: "jay",
name: "Jay",
mark: [
{
id: "5a5d84b94a074119ef2d4553",
name: 70
}
]
}
]
}
]
Since there are multiple nested arrays in your data structure, you need to use forEach those many times
data.forEach( s => //iterate data
s.subs.forEach( t => //iterate subs
( t.mark = t.mark.slice( 1, 2 ) ) ) ); //slice the second value out
Demo
var data = [{
id: 1,
name: "Main",
subs: [{
id: "jay",
name: "Jay",
mark: [{
id: "5a5d84b94a074c49ef2d4553",
name: 100
},
{
id: "5a5d84b94a074119ef2d4553",
name: 70
}
]
}]
}];
data.forEach(s => s.subs.forEach(t => (t.mark = t.mark.slice(1,2))));
console.log(JSON.stringify(data, 0, 4))
In case the last value should be picked?
data.forEach( s => //iterate data
s.subs.forEach( t => //iterate subs
( t.mark = t.mark.slice( -1 ) ) ) ); //slice the last value out
If you are trying to filter a relevant mark by a given id,
you can combine Array#map and Array#filter to achieve it:
Note that i'm also using the Object Rest/Spread Properties proposal (stage 4)
Running example
const state = {
data: [{
id: 1,
name: "Main",
subs: [{
id: "jay",
name: "Jay",
mark: [{
id: "5a5d84b94a074c49ef2d4553",
name: 100
}, {
id: "5a5d84b94a074119ef2d4553",
name: 70
}]
}]
}]
};
const mark_id = '5a5d84b94a074119ef2d4553';
const nextState = {
...state,
data: state.data.map(obj => {
const filteredSubs = obj.subs.map(sub => {
const markById = sub.mark.filter(m => m.id === mark_id);
return {
...sub,
mark: markById
}
});
return {
...obj,
subs: filteredSubs
}
})
};
console.log(nextState);
You can even use lodash which contains many methods that can be handled easily.
Check if this is what you are looking for. (there is a good scope to refactor it but before that would like to understand if thats what you are looking for)
Below is the code that has been used there.
let inputId = "5a5d84b94a074c49ef2d4553";
let filteredData =_.each(_.cloneDeep(data), function(value, key1) {
_.each(value.subs, function(valueSubs, key2) {
var finalSubMark = _.find(valueSubs.mark, function(eachMark) {
return eachMark.id == inputId;
});
_.set(valueSubs, "mark", finalSubMark);
});
});
https://codesandbox.io/s/v065w05rly