I am able to get all unique properties from an array like this,
var array = [{
"firstName": "John",
"lastName": "Doe"
}, {
"firstName": "Anna",
"car": true
}, {
"firstName": "Peter",
"lastName": "Jones"
}];
var result = [];
array.reduce( function(pre, item) {
Object.keys(item).forEach(function(i){
if (result.indexOf(i) === -1){
result.push(i);
}
});
});
console.log(result);
However now I need this output,
[{
"firstName":"John, Anna, Peter",
"car": "true",
"lastName": "Doe, Jones"
}]
but I am not sure how to ?
Various ways. Here's one:
//get unique properties - hence Set, not array, so dups are omitted
let props = new Set(array.map(obj => Object.keys(obj)).flat());
//get non-falsy value for each prop type, as an array
let vals = [...props].map(prop => array.map(obj => obj[prop]).filter(a => a).join(', '));
//merge the two via Object.fromEntries()
let final = Object.fromEntries.call(null, [...props].map((prop, i) => [prop, vals[i]]));
You could achieve that by having a lookup object that store all values for a property. Then manipulate that object by joining all occurences
Below snippet could help you
var array = [
{
firstName: "John",
lastName: "Doe",
},
{
firstName: "Anna",
car: true,
},
{
firstName: "Peter",
lastName: "Jones",
},
]
var lookup = {}
var result = {}
array.forEach((obj) => {
Object.entries(obj).forEach(([key, val]) => {
if (!lookup[key]) {
lookup[key] = [val]
} else {
lookup[key].push(val)
}
})
})
Object.entries(lookup).forEach(([key, val]) => {
result[key] = val.join(', ')
})
console.log(result)
Related
I have an object similar to this:
const obj = {
id: 1,
name: {
"english-us": "John",
"english-uk": "John",
"italian-eu": "Giovanni",
},
};
I want to transfrorm every property name that is a string into a non-string one, like this:
const obj = {
id: 1,
name: {
english_us: "John",
english_uk: "John",
italian_eu: "Giovanni",
},
};
I can't modify the original object. I get it from an axios request.
You could use regex with stringify
let output = JSON.parse(JSON.stringify(obj).replace(/"(.*?)":.*?,?/g,
key=>key.replace(/\-/g, `_`)));
Output
console.log(JSON.stringify(output, null, 4));
/*
{
"id": 1,
"name": {
"english_us": "John",
"english_uk": "John",
"italian_eu": "Giovanni"
}
}*/
If you can copy the object, you could check this solution for declaring the attributes:
link
There are a few ways of achieving this. This example has a function that converts the key on every iteration of the name entries. A new names object is updated with these properties, and is later folded into a new object along with the existing properties of the original object.
const obj = {
id: 1,
name: {
"english-us": "John",
"english-uk": "John",
"italian-eu": "Giovanni",
},
};
const convert = (key) => key.replace('-', '_');
const updatedName = {};
for (const [key, value] of Object.entries(obj.name)) {
updatedName[convert(key)] = value;
}
const newObj = { ...obj, name: updatedName };
console.log(newObj);
You can convert object to JSON and convert back.
const obj = {
id: 1,
name: {
"english-us": "John",
"english-uk": "John",
"italian-eu": "Giovanni",
},
};
console.log(JSON.parse(JSON.stringify(obj)))
Two ways to clone the object and rename all keys from its name property
const obj = {
id: 1,
name: {
"english-us": "John",
"english-uk": "John",
"italian-eu": "Giovanni",
},
};
// clone obj
const myObj = window.structuredClone ?
structuredClone(obj) : JSON.parse(JSON.stringify(obj));
// rename all keys in myObj.name
Object.keys(myObj.name).forEach(key => {
myObj.name[key.replace(/\-/g, `_`)] = myObj.name[key];
delete myObj.name[key];
});
console.log(myObj.name.english_us);
// obj is untouched
console.log(obj.name[`english-us`]);
// myObj.name[`english-us`] does not exist
console.log(myObj.name[`english-us`]);
// alternative: clone and rename in one go
const myObjClone = {
...obj,
name: Object.fromEntries(
Object.entries(obj.name)
.reduce( (acc, [k, v]) =>
[ ...acc, [ k.replace(/\-/g, `_`), v ] ] , [] ) )
};
console.log(myObjClone.name.italian_eu);
// obj is untouched
console.log(obj.name[`italian-eu`]);
// myObjClone.name[`italian-eu`] does not exist
console.log(myObjClone.name[`italian-eu`]);
I am underscore.js newbie and I am trying to iterate through below JSON object and check, if certain fields exists. In this case, I need to bring out the records in all_rec best matching with input.
input = {first_name: "John", surname: "Paul", email: "john.paul#gmail.com"}
all_rec = [
{"id": 1,"first_name": "John","surname": "Paul","email": "john.paul#gmail.com"},
{"id": 2,"first_name": "Kerry","surname": "Morrison","phone": "43567823"},
{"id": 3,"first_name": "John", "phone": "0345433234"}
]
I am expecting below records to be retrieved,
id : 1 ==> Matching all 3 fields ( firstname, surname & email)
id : 3 ==> Matching only firstname (absence of surname & email)
I tried the following code,
let resultData = _.where(all_rec, (
(_.has(all_rec, "first_name") ? {first_name: input.first_name} : true) &&
(_.has(all_rec, "surname") ? {surname: input.surname} : true) &&
(_.has(all_rec, "email") ? {email: input.email} : true) &&
(_.has(all_rec, "mobile") ? {mobile: input.mobile} : true)));
I expect it to bring out records with id: 1 & 3. But, it is bringing out all the records. Not sure as where I am going wrong.
Also, I am not sure, if this can be achieved using underscore.js. Kindly advise.
I'm not sure you can do it with where/findWhere function, but you definitely could achieve it using filter
Underscore Example:
const input = {
first_name: "John",
surname: "Paul",
email: "john.paul#gmail.com"
};
const all_rec = [
{"id": 1,"first_name": "John","surname": "Paul","email": "john.paul#gmail.com"},
{"id": 2,"first_name": "Kerry","surname": "Morrison","phone": "43567823"},
{"id": 3,"first_name": "John", "phone": "0345433234"}
];
const resultData = _.filter(all_rec, item =>
_.keys(item).every(key => _.has(input, key) ? input[key] === item[key] : true));
console.log(resultData);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js"></script>
Vanilla ES6 Example:
const input = {
first_name: "John",
surname: "Paul",
email: "john.paul#gmail.com"
};
const all_rec = [
{"id": 1,"first_name": "John","surname": "Paul","email": "john.paul#gmail.com"},
{"id": 2,"first_name": "Kerry","surname": "Morrison","phone": "43567823"},
{"id": 3,"first_name": "John", "phone": "0345433234"}
];
const resultData = all_rec.filter(item =>
Object.keys(item).every(key => input.hasOwnProperty(key) ? input[key] === item[key] : true));
console.log(resultData);
Function below implements _.has and will return match based on properties on input, and those available records.
input = {first_name: "John", surname: "Paul", email: "john.paul#gmail.com"}
all_rec = [
{"id": 1,"first_name": "John","surname": "Paul","email": "john.paul#gmail.com"},
{"id": 2,"first_name": "Kerry","surname": "Morrison","phone": "43567823"},
{"id": 3,"first_name": "Sue", "phone": "0345433234"}
]
const matcher = (input, all_records) => {
return all_records.filter(record => {
const keysToUse = Object.keys(record).filter(key => _.has(input, key));
if (keysToUse.length === 0) return false;
return keysToUse.every(key => input[key] === record[key]);
})
}
console.log(matcher(input, all_rec));
hi I am trying to create a object map from array of objects using reduce method but did n't find a way to add 2 properties as key . Let say I have array of objects like -
const students = [
{
name: "sam",
age: 26,
},
{
name: 'john",
age: 30,
}
]
i am trying to create a map like
{
sam_26:{
name: "sam",
age: 26,
}
}
my code for reduce function :
students.reduce((obj, student) => {
`${obj[student.name]}_${obj[student.age]}` = student;
return obj;
}, {});
this didn't work . any pointers will be helpful ..thanks!
Create the key with the values taken from the student object. Assign the current student to the obj (the accumulator) using the key:
const students = [{
name: "sam",
age: 26,
},
{
name: "john",
age: 30,
}
];
const result = students.reduce((obj, student) => {
const key = `${student.name}_${student.age}`;
obj[key] = student;
return obj;
}, {});
console.log(result);
A generic approach that uses a callback to create the key:
const keyBy = (arr, cb) =>
arr.reduce((r, o) => {
const key = cb(o);
r[key] = o;
return r;
}, {});
const students = [{"name":"sam","age":26},{"name":"john","age":30}];
const result = keyBy(students, (o) => `${o.name}_${o.age}`);
console.log(result);
You can't assign to the left side with a template literal like that. Try defining the property first, and then assigning it to the object:
const students = [ { name: "sam", age: 26, }, { name: 'john', age: 30, } ];
const finalObj = students.reduce((obj, student) => {
const prop = `${student.name}_${student.age}`;
obj[prop] = student;
return obj;
}, {});
console.log(finalObj);
Hopefully this snippet will be useful
const students = [{
name: "sam",
age: 26,
},
{
name: "john",
age: 30,
}
]
//Using reduce function to add value to the accumalator
var x = students.reduce(function(acc, curr, index) {
// Here acc is the object which is passed as argument,
//In this object checking if it has a key like sam_26 & so on
if (!acc.hasOwnProperty([curr['name'] + '_' + curr['age']])) {
//if not then add the key and add relevant vakues to it
acc[curr.name + '_' + curr.age] = {
name: curr.name,
age: curr.age
}
}
return acc;
}, {});
console.log(x)
I tried this script and it worked. Simply create variable name based on student name and age then assign back to the object
students.reduce((obj, student) => {
var name = student.name + '-' + student.age;
obj[name] = student;
return obj;
}, {});
I have data like this:
{
"-L8BpxbS70KYrZMQUF0W": {
"createdAt": "2018-03-22T16:33:57+08:00",
"email": "ss#ss.ss",
"name": "ss"
},
"-KYrZMQUF0WL8BpxbS70": {
// etc.
}
}
Which I want to turn into this:
[{
id: '-L8BpxbS70KYrZMQUF0W
createdAt: "2018-03-22T16:33:57+08:00",
email: "ss#ss.ss",
name: "ss"
}, {
id: -KYrZMQUF0WL8BpxbS70"
// etc.
}]
I'm started with this:
Object.keys(idBasedObjects).forEach(key => {
console.log(resp[key])
})
But I get undefined.
What's best way of creating this array?
Get the keys and values using Object.entries(), and Array.map() them to to the required form using object spread:
const obj = {"-L8BpxbS70KYrZMQUF0W":{"createdAt":"2018-03-22T16:33:57+08:00","email":"ss#ss.ss","name":"ss"},"-KYrZMQUF0WL8BpxbS70":{}};
const result = Object.entries(obj).map(([id, props]) => ({
id,
...props
}));
console.log(result);
Use Object.keys, Object.assign and map
var output = Object.keys(obj).map( s => Object.assign( obj[s], {id : s} ))
Demo
var obj = {
"-L8BpxbS70KYrZMQUF0W": {
"createdAt": "2018-03-22T16:33:57+08:00",
"email": "ss#ss.ss",
"name": "ss"
},
"-KYrZMQUF0WL8BpxbS70": {
"createdAt": "2018-03-22T16:33:57+08:00",
"email": "s2s#ss.ss",
"name": "ss2"
}
};
var output = Object.keys(obj).map(s => Object.assign(obj[s], {
id: s
}));
console.log(output);
I'm looping over an object to create number of arrays inside dataSet.
dataSet = []
this.props.users.map((item) => {
dataSet.push([item.profile.firstName, item.profile.lastName])
})
How can I apply es6 destructuring? here is what I have tried, but keep getting syntax error.
dataSet = []
this.props.users.map((item) => {
let {firstName, lastName } = item.profile
dataSet.push([firstName, lastName])
})
First of all, you're creating extra work for yourself by performing push inside of map. Map will return an array for you naturally. Try this snippet out:
let props = {
users: [
{
profile: {
firstName: "John",
lastName: "Doe",
sex: "male"
}
},
{
profile: {
firstName: "Jane",
lastName: "Doe",
sex: "female"
}
}
]
};
const newArr = props.users.map(({profile: {firstName, lastName}}) => [firstName, lastName]);
console.log(newArr);