Unstring an object property name javascript - javascript

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`]);

Related

Create objects from main key and value from nested object

I'll keep it simple. Suppose I have an object like this:
let myObj = {
name:{
value: "John",
type: "contains"
},
age:{
value: "5",
type: "contains"
}
}
how can I create a new object that contains the main key but the value is just the value of its nested object, as follows:
let myNewObj = {
name: "John",
age: "5"
}
Thanks in advance.
If you just want to extract the value key for each object, you can do something like this:
let myObj = {
name:{
value: "John",
type: "contains"
},
age:{
value: "5",
type: "contains"
}
}
let newObj = {}
for (const key in myObj) {
newObj[key] = myObj[key].value;
}
console.log(newObj);
// {
// age: "5",
// name: "John"
// }
Convert the object to its entries array and map through it to return [key,value]
Then convert to a new object using Object.fromEntries
let myObj = {
name:{
value: "John",
type: "contains"
},
age:{
value: "5",
type: "contains"
}
}
let myNewObj = Object.fromEntries(Object.entries(myObj).map(([key,{value}])=>[key,value]))
console.log(myNewObj)
In general, to be able to transform all the values of an object's properties according to a mapping function, you can use Object.entries to make an array of [key, value] arrays for each property, and then use Object.fromEntries to reconstitute an object from those arrays. You can provide a generic transformation function in the middle of that operation like this:
const transformValues = (obj, transform) =>
Object.fromEntries(Object.entries(obj).map(([key, value]) => [key, transform(value)]));
The transform function you need in your specific case will take the property value (which is an object) and just return its value property. Like this: ({ value }) => value (This is pretty easy with destructuring.)
let myObj = {
name: {
value: "John",
type: "contains"
},
age: {
value: "5",
type: "contains"
}
}
const transformValues = (obj, transform) =>
Object.fromEntries(Object.entries(obj).map(([key, value]) => [key, transform(value)]));
const result = transformValues(myObj, ({ value }) => value);
console.log(result);

Best way to replace an array with its contents from inside an object

I'm given the following JavaScript object:
{
name: [
{
"firstName":"First ",
"lastName":"Last"
}
],
age: 21
}
The name property (or other similar complex props) are always provided as an object within an array, even though there can only ever be a single value.
I need to save the information as an object that looks like this (without the array around the value of the name property):
{
name: {
firstName: 'First ',
lastName: 'Last'
},
age: 21
}
I need a generic function that doesn't reference a particular property name because that changes depending on the query. Here's my solution:
const object = {
name: [{"firstName":"First ","lastName":"Last"}],
age: 21
}
const data = {}
for (const property in object) {
const value = object[property]
if (Array.isArray(value)) {
data[property] = value[0]
} else {
data[property] = value
}
}
Which returns the properly formatted object.
My question is whether this is the most performant and/or most obvious way to get the result I'm looking for?
If you want abstraction over the entire object you could do something like this:
const object1 = {
name: [{"firstName":"First ","lastName":"Last"}],
age: 21
}
const rebuildObject = (object) => Object.keys(object).reduce((result, key) => {
const value = object[key];
result[key] = Array.isArray(value) ? object[key][0] : value;
return result;
}, {});
const newObject = rebuildObject(object1);
console.log(newObject);
If the name array is guaranteed to only ever have 1 object inside of it and is always an array, you can do:
const data = {
name: [
{
"firstName":"First ",
"lastName":"Last"
}
],
age: 21
};
if(data.name.length === 0) {
const newObj = {
name: data.name[0],
age: data.age
};
};
console.log(newObj); // { firstName: 'First ', lastName: 'Last', age: 21 }
Edit
When name is actually any arbitray key name, you can do:
const data = {
name: [
{
"firstName":"First ",
"lastName":"Last"
}
],
age: 21
};
const objKeys = Object.keys(data);
console.log(objKeys) // > Array ["name", "age"]
let arbKey = objKeys.filter(objKey => objKey !== "age")[0];
console.log(arbKey); // > "name"
const newObj = {
arbKey: data[arbKey][0],
age: data.age
};
console.log(newObj); // > Object { arbKey: Object { firstName: "First ", lastName: "Last" }, age: 21 };
Note: This only works based on the object schema you have provided. If your actual code is different, you will need to tweak it.
this is a generic function that can serve what you need, call the function with the object and property name you want to transform.
function arrayToObject(object, property) {
if(object[property] && Array.isArray(object[property])) {
object[property] = object[property][0];
}
return object;
}
// let data = {
// name: [
// {
// "firstName":"First ",
// "lastName":"Last"
// }
// ],
// age: 21
// }
// console.log(arrayToObject(data, 'name'));
// { name: { firstName: 'First ', lastName: 'Last' }, age: 21 }
update:
in case we don't know the property name,
we can use this version.
function arrayToObject(object) {
for(let key in object){
if(Array.isArray(object[key])) {
object[key] = object[key][0];
}
}
return object;
}
let a = {
name: [
{
"firstName":"First ",
"lastName":"Last"
}
],
age: 21
}
a.name = a.name[0];

How to do: All contents into one object in this case

I'm trying to modify object's key to given name + its key name and want to get all into one object.
Source:
aodl = {"name1": "Jhon", "name2": "Tiger", "name3": "Jack", ...}
When I tried
console.log(
Object.entries(aodl).map(([key, value]: [string, string]) => {
return { ["aodl_" + key]: value };
})
);
Then I get
[ {"aodl_name1": "Jhon"}, {"aodl_name2": "Tiger"}, {"aodl_name3": "Jack"}, {…}, {…}, ...]
I want to get all object's contents and I want to put them into one object
{
"aodl_name1": "Jhon",
"aodl_name2": "Tiger",
"aodl_name3": "Jack",
...
}
How to do it?
Please let me know if you need more info about it.
You could either use Object.fromEntries
var aodl = { foo: 'foo', bar: 'bar' },
object = Object.fromEntries(Object
.entries(aodl)
.map(([key, value]) => ["aodl_" + key, value])
);
console.log(object);
Or map single objects and get a single object with Object.assign.
var aodl = { foo: 'foo', bar: 'bar' },
object = Object.assign(
{},
...Object.entries(aodl).map(([key, value]) => ({ ["aodl_" + key]: value }))
);
console.log(object);
You could use simply Object.assign()
const aodl = { name: 'John', name1: 'Wick' }
console.log(Object.assign({}, ...Object.entries(aodl).map(([key, value]) => ({['aodl_'+key]: value}))))

Converting to Correct Object Format from Array

I am aware of options like the spread operator and Object.assign() when it comes to converting an array to an object, however, I am having difficulty figuring out how to format the final object in the format I need.
My original array looks like this:
let propsArray = [ { id: '1' },
{ 'name.first': 'john' },
{ 'name.last': 'smith' } ]
The object I want from this data needs to look like this:
{
"id" : 1,
"name" : {
"first" : "john",
"last" : "smith"
}
}
What I've tried so far, using object.assign(), ends up adding numbers as property keys in the resulting object, which is clearly not what I'm looking for:
let finalObj = Object.assign({}, propsArray);
How can I get the resulting object formatted the way I need here?
You need a deeper look into the object and take the splitted key and reduce them by taking an object with the property or an empty object. At the end assign the value.
var data = [{ id: '1' }, { 'name.first': 'john' }, { 'name.last': 'smith' }],
result = data.reduce((r, o) => {
Object.entries(o).forEach(([k, v]) => {
var keys = k.split('.'),
last = keys.pop();
keys.reduce((q, k) => q[k] = q[k] || {}, r)[last] = v;
});
return r;
}, {});
console.log(result);
Try this:
const data = [
{
"id": "1"
},
{
"name.first": "john"
},
{
"name.last": "smith"
}
]
const result = Object.entries(Object.assign({}, ...data))
.reduce((acc,[k,v])=>{
[first, last] = k.split('.');
if (!last) {
acc[k] = v
} else {
acc[first] = acc[first] || {};
acc[first][last] = v;
}
return acc
}, {})
console.log(result);

js object property creation from keys

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;
}, {});

Categories

Resources