I am stuck with mapping in array of objects.
Please find the below code
const array = [
{
user: "User1",
cities: ["city1", "city2", "city3"],
},
{
user: "User2",
cities: ["city2", "city3", "city4"],
},
];
let x = {};
array.map((item) => {
let user = item.user;
let cities = item.cities;
cities.map((city) => (x[city] = user));
});
Now it returns like this:
const resArray = [{ city1: "User1", city2: "User2", city3: "User2", city4: "User2" }]
I want the array like this:
const resArray = [
{ city1: ["User1"] },
{ city2: ["User1", "User2"] },
{ city3: ["User1", "User2"] },
{ city4: ["User2"] },
];
Can anyone please help me out.
Thanks
Try this
let x = {};
array.forEach((item) => {
item.cities.forEach((city) => {
x[city] = item.cities.includes(city) ? [...x[city] ? x[city] : [], item.user] : [];
});
});
You have been assigning user to city each time. Instead the x[city] should be an array and you should push the new user inside that array.
Try this,
const array = [
{
user: "User1",
cities: ["city1", "city2", "city3"],
},
{
user: "User2",
cities: ["city2", "city3", "city4"],
},
];
let x = {};
array.map((item) => {
let user = item.user;
let cities = item.cities;
cities.map((city) => {
if(x[city] && x[city].length) {
x[city].push(user);
} else{
x[city] = [user];
}
});
});
const res = Object.keys(x).map(key => { return {[key]: x[key]}});
console.log(res);
Related
I have an array
const dataCheck = ["Rohit","Ravi"];
I have another array of object
const userData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit" },
{ name: "Ravi" },
];
I want to check if any value in dataCheck is present in the userData and then return a new array with the below data
const newData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit", status: "present" },
{ name: "Ravi", status: "present" },
];
I tried to do something using loops but not getting the expected results
const dataCheck = ["Rohit", "Ravi"];
const userData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit" },
{ name: "Ravi" }
];
let newDataValue = {};
let newData = [];
userData.forEach((user) => {
const name = user.name;
dataCheck.forEach((userName) => {
if (name === userName) {
newDataValue = {
name: name,
status: "present"
};
} else {
newDataValue = {
name: name
};
}
newData.push(newDataValue);
});
});
console.log(newData);
My trial gives me repeated results multiple results which is just duplicates
You should use map() and a Set.
const dataCheck = ["Rohit","Ravi"];
const userData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit" },
{ name: "Ravi" },
];
const set = new Set(dataCheck);
const output = userData.map(data => set.has(data.name) ? ({...data, status: "present"}): data)
console.log(output)
.as-console-wrapper { max-height: 100% !important; top: 0; }
A Set allows for lookups in O(1) time and therefore this algorithm works in O(n) time. If you would use the array for lookups (e.g. using indcludes(), find() etc.) the runtime would be O(n²). Although this will certainly not matter at all for such small arrays, it will become more relevant the larger the array gets.
map() is used here because you want a 1:1 mapping of inputs to outputs. The only thing to determine then is, what the output should be. It is either the input, if the value is not in the Set, or it is the input extended by one property status set to "present". You can check for the presence in a Set using the has() method and can use the ternary operator ? to make the decision which case it is.
const dataCheck = ["Rohit", "Ravi"];
const userData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit" },
{ name: "Ravi" },
];
// map through every object and check if name property
// exists in data check with help of filter.
// if it exists the length of filter should be 1 so
// you should return { name: el.name, status: "present" } else
// return { name: el.name }
let newData = userData.map((el) => {
if (dataCheck.filter((name) => name === el.name).length > 0) {
return { name: el.name, status: "present" };
} else {
return { name: el.name };
}
});
console.log("newdata: ", newData);
A better approach would be to use map over userData array, find for matching element in dataCheck, if found return matching element + a status key or just return the found element as it is.
const dataCheck = ["Rohit","Ravi"];
const userData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit" },
{ name: "Ravi" },
];
const getUpdatedObject = () => {
return userData.map(userData => {
const userDetail = dataCheck.find(data => userData.name === data);
if(userDetail) return {userDetail, status:"present"}
else return {...userData}
});
}
console.log(getUpdatedObject())
Working fiddle
Loop through userData, check if name is includes in dataCheck. If true add status 'present'.
const dataCheck = ["Rohit","Ravi"];
const userData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit" },
{ name: "Ravi" },
];
for (let user of userData) {
if(dataCheck.includes(user.name)) {
user.status = 'present'
}
}
console.log(userData)
You are seeing repeated results due to the second loop dataCheck.forEach((userName) => { as every loop of dataCheck will fire the if/else statement and add something to the final array. However many values you add to dataCheck will be however many duplicates you get.
Only need to loop through one array and check if the value is in the other array so no duplicates get added.
const dataCheck = ["Rohit", "Ravi"];
const userData = [{ name: "Sagar" }, { name: "Vishal" }, { name: "Rohit" }, { name: "Ravi" }];
let newDataValue = {};
let newData = [];
// loop thru the users
userData.forEach((user) => {
// set the user
const name = user.name;
// check if in array
if (dataCheck.indexOf(name) >= 0) {
newDataValue = {
name: name,
status: "present",
};
}
// not in array
else {
newDataValue = {
name: name,
};
}
newData.push(newDataValue);
});
console.log(newData);
So you will do like this :
const dataCheck = ["Rohit","Ravi"];
const userData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit" },
{ name: "Ravi" },
];
const newUserData = userData.map( user => {
dataCheck.forEach( data => {
if( data === user.name )
user.status = "present";
});
return user;
} );
console.log( newUserData );
I have an array of objects that I want to iterate over and create a new array of objects.
First I map over the data, then I loop through each object to extract the values. I want to store the Location name and value from each object.
My code is returning null results. I can't change the way data is declared. Can someone help me understand why I keep getting null results?
[
{
"euValue": null,
"asValue": null
}
]
const data = [{
Locations: [{
Location: {
Name: "Europe"
},
Value: "Ireland"
},
{
Location: {
Name: "Asia"
},
Value: "China"
}
]
}];
const formatData = () => {
let formattedData = [];
let euValue, asValue;
formattedData = data.map(location => {
for (const l in location) {
if (location.hasOwnProperty(l)) {
const _this = location[l];
euValue = _this.Location === "Europe" ? _this.Value : null;
asValue = _this.Location === "Asia" ? _this.Value : null;
}
}
return {
euValue,
asValue
};
});
return formattedData;
};
const newData = formatData();
console.log(newData);
Edit
Expected result is
[
{
"euValue": “Ireland”,
"asValue": “China”
}
]
Assuming that inside data you could have multiple objects with a Location array that have only 2 objects (one for Europe and another one for Asia) you should change your function to something like this
const data = [
{
Locations: [
{
Location: { Name: "Europe" },
Value: "Ireland"
},
{
Location: { Name: "Asia" },
Value: "China"
}
]
}
];
const formatData = () => {
// iterate all data objects
return data.map((topLocation) => {
const res = {};
// loop over Location children objects
topLocation.Locations.forEach((location) => {
const { Name } = location.Location;
// decide where to save Value base on the Location.name
if (Name === "Europe") {
res.euValue = location.Value;
} else if (Name === "Asia") {
res.asValue = location.Value;
}
});
return res;
});
};
const newData = formatData();
console.log(newData);
you missing a second loop also you overwriting the usValue and euValue and you better use forEach instead of map in this case.
const data = [{
Locations: [{
Location: {
Name: "Europe"
},
Value: "Ireland"
},
{
Location: {
Name: "Asia"
},
Value: "China"
}
]
}];
const formatData = (data) => {
let formattedData = [],
values = {};
data.forEach(location => {
for (const l in location) {
if (location.hasOwnProperty(l)) {
const _this = location[l];
_this.forEach(el => {
if (el.Location.Name === "Europe") {
values["euValue"] = el.Value || null
}
if (el.Location.Name === "Asia") {
values["asValue"] = el.Value || null
}
})
}
}
});
formattedData.push(values)
return formattedData;
};
console.log(formatData(data))
I don't know what do you want to get from your code but this code may help you.
const data = [{
Locations: [{
Location: {
Name: "Europe"
},
Value: "Ireland"
},
{
Location: {
Name: "Asia"
},
Value: "China"
}
]
}];
const formatData = () => {
let formattedData = [];
formattedData = data.map(location => {
let euValue = [],
asValue = [];
for (const l in location.Locations) {
if (location.Locations.hasOwnProperty(l)) {
const _this = location.Locations[l];
if (_this.Location.Name === "Europe")
euValue.push(_this.Value);
else if (_this.Location.Name === "Asia")
asValue.push(_this.Value);
}
}
return {
euValue,
asValue
};
});
return formattedData;
};
const newData = formatData();
console.log(newData);
I'm sure many of the other answers are fine but the way I did it was to do the classic for loop to iterate over the data. I would have liked to have kept your ternary operators but I think you may need the if/else syntax.
var data = [{
Locations: [{
Location: {
Name: "Europe"
},
Value: "Ireland"
},
{
Location: {
Name: "Asia"
},
Value: "China"
}
]
}];
const formatData = () => {
let formattedData = [];
let euValue, asValue;
formattedData = data.map(location => {
for (const l in location) {
if (location.hasOwnProperty(l)) {
const _this = location[l];
for (let i = 0; i < _this.length; i++) {
if (_this[i].Location.Name === "Europe") {
euValue = _this[i].Value;
} else if (_this[i].Location.Name === "Asia") {
asValue = _this[i].Value;
} else {
euValue, asValue = null;
}
}
}
}
return {
euValue,
asValue
};
});
return formattedData;
};
const newData = formatData();
console.log(newData);
Using Array.prototype.flatMap() might help you get the array you desire in a cleaner way:
const data = [{
Locations: [{
Location: {
Name: "Europe"
},
Value: "Ireland"
},
{
Location: {
Name: "Asia"
},
Value: "China"
}
]
}];
const formatData = () => {
const formattedData = data.flatMap(item => {
const object = {}
item.Locations.map(location => {
const continent = location.Location.Name
let country = {}
if (continent === 'Europe') country = {
euValue: location.Value
}
if (continent === 'Asia') country = {
asValue: location.Value
}
Object.assign(object, country)
});
return object
});
return formattedData;
}
const newData = formatData();
console.log(newData);
Into the below code there are the usersData object which contains the usersList array.
const usersData = {
usersList: [
{
user: "user1",
langSpeak: ["IND","SPN"],
},
{
user: "user2",
langSpeak: ["IND"],
},
{
user: "user1",
langSpeak: ["IND", "SPN", "JPN"],
},
{
user: "user3",
langSpeak: ["IND", "SPN"],
},
{
user: "user3"
}
]
};
let usersKey = ["user","langSpeak"];
let usersValue = ["user1","IND","SPN"];
let userColl = usersData.usersList.filter(userObj => {
return usersKey.forEach( usersKey => {
if(Array.isArray(userObj[usersKey])){
return userObj[usersKey] && usersValue.forEach(x => {
console.log("x===" + usersKey)
return userObj[usersKey].includes(x)
});
}
if(!Array.isArray(userObj[usersKey])){
console.log(usersKey)
return usersValue.includes(userObj[usersKey]);
}
});
});
console.log(userColl);
There are the usersKey and usersValue.
Code is already there for the filter key and values.
I checked into the filter function if the value contains the array or not depending on that return the filter data.
And the final output is stored into the userColl variable.
Currently I am getting null in output but I am expecting first and third userList object; also the condition is that I do not want to change the usersKey and usersValue.
Thanks in advance.
Instead of using Array.forEach you should use Array.every to check the presence of the required data in the given array.
Then using the boolean returned from the every call can be used as the filter criteria to filter the data.
The Array.forEach doesn't return anything but Array.filter expects a boolean predicate to test but in your code forEach will return undefined.
Also the second key should be langSpeak instead of code:
const usersData = {usersList:[{user:"user1",langSpeak:["IND","SPN"]},{user:"user2",langSpeak:["IND"]},{user:"user1",langSpeak:["IND","SPN","JPN"]},{user:"user3",langSpeak:["IND","SPN"]},{user:"user3"}]};
let usersKey = ["user","langSpeak"];
let langValues = ["IND","SPN","JPN"];
let userValues = ["user1"];
let userColl = usersData.usersList.filter(userObj => {
return usersKey.every( usersKey => {
if(Array.isArray(userObj[usersKey])){
return langValues.every(x => {
return userObj[usersKey].includes(x)
});
}
else{
return userValues.every(user => user === userObj[usersKey]);
}
});
});
console.log(userColl);
forEach doesn't return anything - change your code slightly to use every and some. I also modified it slightly with ternaries:
const usersData = {
usersList: [{
user: "user1",
langSpeak: ["IND", "SPN"],
},
{
user: "user2",
langSpeak: ["IND"],
},
{
user: "user1",
langSpeak: ["IND", "SPN", "JPN"],
},
{
user: "user3",
langSpeak: ["IND", "SPN"],
},
{
user: "user3"
}
]
};
let usersKey = ["user", "langSpeak"];
let usersValue = ["user1", "IND", "SPN"];
let userColl = usersData.usersList.filter(userObj => usersKey.every(k => Array.isArray(userObj[k]) ? usersValue.some(v => userObj[k].includes(v)) : usersValue.includes(userObj[k])));
console.log(userColl);
You can use filter to filter the array. Use every to check if all elements is including a certain string.
const usersData = {"usersList":[{"user":"user1","langSpeak":["IND","SPN"]},{"user":"user2","langSpeak":["IND"]},{"user":"user1","langSpeak":["IND","SPN","JPN"]},{"user":"user3","langSpeak":["IND","SPN"]},{"user":"user3"}]}
let userFilter = "user1"; //Assign a variable for filtering user
let langFilter = ["IND", "SPN"]; //Assign a variable for filtering language
let result = usersData.usersList.filter(o => o.user == userFilter && o.langSpeak && langFilter.every(e => o.langSpeak.includes(e)));
let finalResult = { //Contruct the final object
usersList: result
}
console.log(finalResult);
If you really have to use usersKey and usersValue, you can use a reduce to summarize the filter, like:
const usersData = {"usersList":[{"user":"user1","langSpeak":["IND","SPN"]},{"user":"user2","langSpeak":["IND"]},{"user":"user1","langSpeak":["IND","SPN","JPN"]},{"user":"user3","langSpeak":["IND","SPN"]},{"user":"user3"}]}
let usersKey = ["user", "langSpeak"];
let usersValue = ["user1", "IND", "SPN"];
let filter = usersKey.reduce((c, v, i, a) => {
c[v] = i + 1 === a.length ? usersValue.slice(i) : [usersValue[i]];
return c;
}, {});
let result = usersData.usersList.filter(o => Object.entries(filter).every(([k, v]) => v.every(x => o[k].includes(x))));
let finalResult = {
usersList: result
}
console.log(finalResult);
You can consider changing the variables you are using as filter parameters to an object, or maybe a Map().
Note that your approach with variables can present issues in some cases, for example, what would happen if some user is named IND. How will you know if some element of the array usersValue is related to filtering the property user or the property langSpeak?
If you use an object, then you can proceed like this:
const usersData = {
usersList: [
{user: "user1", langSpeak: ["IND","SPN"]},
{user: "user2", langSpeak: ["IND"]},
{user: "user1", langSpeak: ["IND", "SPN", "JPN"]},
{user: "user3", langSpeak: ["IND", "SPN"]},
{user: "user3"}
]
};
let filterObj = {
"user": ["user1"],
"langSpeak": ["IND", "SPN"]
};
let userColl = usersData.usersList.filter(userObj =>
{
return Object.entries(filterObj).every(([k, v]) =>
{
let uVal = userObj[k];
if (Array.isArray(uVal))
return v.every(x => uVal.includes(x));
else
return v.includes(uVal);
});
});
console.log(userColl);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
You could normalize your constraints and take an array, bcause it's easy iterable with another array of a key value and the needed values in other arrays.
Then iterate constraints and check if the value from the object is an array or not. Depending on this check iterate the values or take a single check.
var usersList = [{ user: "user1", langSpeak: ["IND", "SPN"] }, { user: "user2", langSpeak: ["IND"] }, { user: "user1", langSpeak: ["IND", "SPN", "JPN"] }, { user: "user3", langSpeak: ["IND", "SPN"] }, { user: "user3" }],
constraints = [
["user", "user1"],
["langSpeak", "IND", "SPN"]
],
result = usersList.filter(o => constraints.every(([key, ...values]) => Array.isArray(o[key])
? values.every(v => o[key].includes(v))
: values.includes(o[key])
));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
When i push into my array, it overwrite the last element added.
Here is my code:
const array = [{ name: [] }];
const test = `result1
result2
result3`;
const ways = test.split(/[\n\r]+/).map(aaa => (aaa));
array.forEach((obj) => {
ways.forEach((element) => {
obj.item = [{ result: element }];
});
});
The output i get :
[
{
"name": [],
"item": [{ "result": "result3" }]
}
]
The output i want :
[
{
"name": [],
"item": [
{ "result": "result1" },
{ "result": "result2" },
{ "result": "result3" }
]
}
]
const array = [{ name: [] }];
const test = `result1
result2
result3`;
const ways = test.split(/[\n\r]+/).map(aaa => (aaa));
array.map((obj) => {
obj.item = [];
ways.map((element) => {
obj.item .push([{ result: element }]);
});
});
console.log(array);
You have to declare obj.item as an array and instead of equating values you should push them in the array
const array = [{
name: []
}];
const test = `result1
result2
result3`;
const ways = test.split(/[\n\r]+/).map(aaa => (aaa));
array.forEach((obj) => {
obj.item = [];
ways.forEach((element) => {
obj.item.push({
result: element
});
});
});
console.log(array)
Using reduce method
const test = `result1
result2
result3`;
const res = test.split(/[\n\r]+/).map(aaa => (aaa)).reduce((all, acc) => {
const [a] = all
a.item.push({
"result": acc
})
return all
}, [{
name: [],
item: []
}])
console.log(res)
I want to add data like this
category1
company1
company2
company3
category2
company1
company2
company3
my code
getlist() {
var list = this.lists;
var category
// var company
this.$http.get("/getlist")
.then((res) => {
var obj = res.data;
for(var [key] in obj) {
var company =[];
for(var i in obj[key].company) {
company.push( obj[key].company[i].name)
}
console.log(company);
list.push({
"category_name" : obj[key].name,
"companies": [
{name: company}
]
})
list.category_name = '',
list.companies = '',
company= ''
}
})
},
list form is look like this
{
category_name: 'Category1',
companies: [
{name: 'company1'},
]
},
and data is look like this
[
{
"name": "Category2",
"company": [
{
"name": "company1"
}
{
"name": "company2"
}
]
}
{
"name": "Category2",
"company": [
{
"name": "company1"
}
{
"name": "company2"
}
]
}
]
I don't know how to use forloop in this case.
Can it use double for loop in list.push()?
It is very tired for me..
As I understand, you just want to rename the keys of data objects you retrieve from the server.
This should do it:
getlist() {
this.$http.get('/getlist')
.then(res => {
let list = [];
for (let item of res.data) {
let newItem = {
category_name: item.name,
companies: item.company
}
list.push(newItem);
}
this.lists = list;
})
.catch(err => {
console.error('Error retrieving "/getlist":', err)
});
}