When working with an object like the following, what is the most effective way to build a new object based on the current object's keys? The keys serve as the reference to where it should be in the new object - activityName1 would be equal to the first element name of the new activities nested array, activityName2 equal to the second element name of the array & so on.
const obj = {
activityName1: "Bingo",
activityName2: "Bazinga",
activityType1: "Dog",
activityType2: "Term",
description: "Games are fun.",
name: "Patty"
};
Desired object:
const newObj = {
activities: [
{name: "Bingo", type: "Dog"},
{name: "Bazinga", type: "Term"}
],
description: "Games are fun.",
name: "Patty"
};
My initial thoughts were to use reduce & Object.assign, but the building of the new object returns only a single key/value pair:
Object.keys(variables).reduce((obj, key) => {
if (key.includes('activity')) {
return Object.assign(obj, {
[key[key.length - 1]]: { activities: { [key]: variables[key] } } });
}
return obj;
}, {});
Results in a new activities array like:
[
1: {activities: {type: "Dog"},
2: {activities: {type: "Term"}
]
The only use of mapping is to look for those keys that start activityName and use those to build up your array of activities. You can reuse the key replacing activityName with activityType to get the associated type.
const obj = {
activityName1: "Bingo",
activityName2: "Bazinga",
activityType1: "Dog",
activityType2: "Term",
description: "Games are fun.",
name: "Patty"
};
var result = {
activities: Object.keys(obj).filter(k => k.startsWith("activityName")).map(k => ({
name: obj[k],
type:obj[k.replace("activityName","activityType")]
})),
description: obj.description,
name: obj.name
}
console.log(result);
Related
I have a object which has some properties for one user, and I have array of objects which is returned from API.
My goal is to check which object of Array of objects has the same property as the one single initial object, and then it should return only part of it's properities.
I have tried to use .map on Array of objects but it seems not workig.
Below is the code example. I have also prepared codesandbox if You wish.
const user =
{
name: "jan",
lastName: "kowalski",
fullName: "jan kowalski",
car: "audi"
}
;
const usersAnimal = [
{
name: "jan",
lastName: "kowalski",
fullName: "jan kowalski",
animal: "cat",
animalSize: "small",
animalName: "Bat"
},
{
name: "john",
lastName: "smith",
fullName: "john smith",
animal: "dog",
animalSize: "middle",
animalName: "Jerry"
},
{
name: "Anna",
lastName: "Nilsson",
fullName: "Anna Nilsson",
animal: "cow",
animalSize: "big",
animalName: "Dorrie"
}
];
const filtered = usersAnimal.map((userAnimal)=>userAnimal.fullName === user.fullName && return userAnimal.animalName & userAnimal.animalSize & userAnimal.animal);
thanks
https://codesandbox.io/s/admiring-edison-qxff42?file=/src/App.js
For case like this, it would be far easier if you filter it out first then proceed using map:
const filtered = usersAnimal
.filter((animal) => animal.fullName === user.fullName)
.map(({ animalName, animalSize, animal }) => {
return {
animalName,
animalSize,
animal
};
});
I am providing a for loop solution as I haven't learnt many array methods in javascript.
For me the simplest option is to use a for loop and an if check to loop through the arrays values to check for included values.
for (let v in usersAnimal) {
if (usersAnimal[v].fullName === user.fullName) {
console.log(usersAnimal[v])
}
}
The code above will log the entire usersAnimal object containing the fullname we are looking for.
{
name: 'jan',
lastName: 'kowalski',
fullName: 'jan kowalski',
animal: 'cat',
animalSize: 'small',
animalName: 'Bat'
}
commented for further understanding
for (let v in usersAnimal) {
//loops though the array
if (usersAnimal[v].fullName === user.fullName) {
//when the index value 'v' has a fullname that matches the user fullname value
// it passes the if check and logs that object value
return console.log(usersAnimal[v])
//return true...
}
//return null
}
//etc
If you want to filter, I recommend you to use filter.
The map method will create a new array, the content of which is the set of results returned by each element of the original array after the callback function is operated
const user = {name:"jan",lastName:"kowalski",fullName:"jan kowalski",car:"audi"};
const usersAnimal = [{name:"jan",lastName:"kowalski",fullName:"jan kowalski",animal:"cat",animalSize:"small",animalName:"Bat"},{name:"john",lastName:"smith",fullName:"john smith",animal:"dog",animalSize:"middle",animalName:"Jerry"}];
// Get an array of matching objects
let filtered =
usersAnimal.filter(o => o.fullName === user.fullName);
// You get the filtered array, then you can get the required properties
filtered.forEach(o => {
console.log(
'animal:%s, animalSize:%s, animalName:%s',
o?.animal, o?.animalSize, o?.animalName
);
});
// Then use map to process each element
filtered = filtered.map(o => {
const {animal, animalSize, animalName} = o;
return {animal, animalSize, animalName};
});
console.log('filtered', filtered);
I have a js file that is just a an array with the name and type of person. I am trying to write a function in my other file to iterate through that array of objects and return just the object that matches a certain criteria. Here is my code.
person.js
export const persons_options = [
{
name: 'Andrew',
type: 'Athlete',
},
{
name: 'Paul',
type: 'Worker',
},
{
name: 'Phil',
type: 'Developer',
},
]
utils.js
// params initialized already
person_type = params.subType
const name = persons_options.map((option) => {
if(person_type === option.type){
return option.name
}
})
const person = name
The issue is I know map creates a new array so the output is ,,Phil. How would I just return one of the object names instead of all of them.
find() will do the work
let persons_options = [
{
name: 'Andrew',
type: 'Athlete',
},
{
name: 'Paul',
type: 'Worker',
},
{
name: 'Phil',
type: 'Developer',
},
]
let obj = persons_options.find(o => o.type === 'Developer');
//to return name
console.log("name",obj.name);
console.log(obj);
You need to use the find function.
See here the list of functions that you can call on an array:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#instance_methods
filter might best suit your case if multiple results may be returned.
So I've been stumped on this for hours and I can't really figure out an elegant solution to solve this problem. Let's say I have this:
let Fields = {
GAME: [
{ code: '{{GTAV}}', title: { en: "grnti"} },
{ code: '{{GTA5}}', title: { en: "Grand theph " } },
]
};
How can I turn this into a new format that looks like this ?
let Fields = {
tags: [
{ name: 'GAME', tags:[
{ name: 'grnti', value: "{{GTAV}}" },
{ name: 'Grand theph', value: "{{GTA5N}}" }
]},
]};
I tried to create a function to do the job , but for some reason my brain cannot seem to grasp the solution. Any help please !
A simple version of this might look like the following:
const transform = (fields) => ({
mergeTags: Object .entries (fields) .map (([name, innerFields]) => ({
name,
mergeTags: innerFields .map (({code, title: {en}}) => ({name: en, value: code}))
}))
})
const fields = {RECIPIENT: [{code: '{{RECIPIENT.LN}}', title: {en: "name"}}, {code: '{{RECIPIENT.FN}}', title: {en: "first name" }}]}
console .log (transform (fields))
But from your nested mergeTags properties, I'm guessing that there is something recursive going on. If so, we need more information about the input and output structures.
i just threw a nested reduce function together.
const transformed = Object.entries(Fields).reduce((tags, [key, value]) => {
const mergedTags = value.reduce((codes, code) => {
codes.mergeTags.push({name: code.title.en, value: code.code});
return codes;
}, {name: key, mergeTags: []})
tags.mergeTags.push(mergedTags)
return tags;
}, {mergeTags: []})
Does that work for you?
It is hard to tell exactly from your question what you are hoping to accomplish as well as the shape of your data. Based on your question though, you would probably want to use the Object.keys and map functions
let Fields = {
RECIPIENT: [
{ code: '{{RECIPIENT.LN}}', title: { en: "name" } },
{ code: '{{RECIPIENT.FN}}', title: { en: "first name" } },
]
};
// gets the keys of the 'Fields' object(in this case only 'RECIPIENT'
let newFields = Object.keys(Fields)
// each key should create a new object with the 'key' from the original object as the 'name' of the new object
.map(key => ({
name: key,
// 'Fields[key]' gets the array from the 'RECIPIENT' property and then creates a new object from each object in the original array, mapping the 'title.en' property in the original object to 'name' in the new object and 'code' in the original object to 'value' in the new object
mergeTags: Fields[key].map(property => ({
name: property.title.en,
value: property.code
}))
}));
console.log(newFields);
Here's a clean way that may seem a bit like magic, but I'll walk you through what's going on.
let Fields = {
RECIPIENT: [
{ code: '{{RECIPIENT.LN}}', title: { en: "name"} },
{ code: '{{RECIPIENT.FN}}', title: { en: "first name" } },
]
};
const { pipe, fork, map, get } = rubico
const Transformed = pipe([
Object.entries, // { RECIPIENT: [...] } => [['RECIPIENT', [...]]
fork({
mergeTags: map(fork({ // iterate through each entry ['RECIPIENT', [...]]
name: get(0), // name is the item at index 0 of each entry
mergeTags: pipe([
get(1), // mergeTags starts with index 1 of each entry, the array of code+title objects
map(fork({ // iterate through the array of code + title objects and create new objects
name: get('title.en'), // name is title.en of each object
value: get('code'), // value is title.code of each object
})),
]),
})),
}),
])(Fields)
console.log(JSON.stringify(Transformed, null, 2))
<script src="https://unpkg.com/rubico"></script>
Disclaimer: I am the author of rubico
You can examine these methods in depth at the documentation
I'm learning to manipulate JSON data and I am stuck trying to figure out how to cajole the following JSON into what I want as shown below:
Any pointers to function/terms/concepts that I should learn for this sort of problem would be greatly appreciated! Thanks
JSON object
{
car: 1,
van: 5,
cat: 99999999999999999999999
}
Desired outcome:
items: [
{ "type": "car", "value": "1"},
{ "type": "van", "value": "5"},
{ "type": "cat", "value": "99999999999999999999999"}
]
You can use a combination of Object.entries and Array.prototype.map:
const obj = { car: 1, van: 5, cat: 99999999999999999999999 };
let list = Object.entries(obj) // [["car",1],["van",5],["cat",99999999999999999999999]]
.map(x => ({ type: x[0], value: x[1] }));
console.log(list);
Or, with some destructuring:
const obj = { car: 1, van: 5, cat: 99999999999999999999999 };
let list = Object.entries(obj)
.map(([type, value]) => ({ type, value }));
console.log(list);
The callback to map:
([type, value]) => ({ type, value })
Expects an array as parameter: [type, value]. The first value in that array is assigned to type, the second one to value.
Then we use a shorthand form to set these values in our returned object:
=> ({ type, value })
I'm a beginner. I tried to solve the problem and this is the best I can come up with, tested in Node.js 10.
const obj = {"car": 1, "van": 5, "cat": 999999}
const items = []
for (let key in obj) {
items.push({"type": key, "value": obj[key]})
}
console.log(items)
One thing I am slightly confused about is the difference between for..in vs for..of, I'm currently looking into it.
Object.keys will return:
['car', 'van', 'cat'];
On this array you can use Array's map function which creates a new array with the results of calling a provided function on every element in the calling array.
var a = {
car: 1,
van: 5,
cat: 99999999999999999999999
}
m = Object.keys(a).map((v)=>{
return {
type: v,
value: a[v]
}
})
console.log(m);
#GustavMahler hope you understand. To learn more about array functions you should look map, reduce and filter.
This one uses object.keys
let js = {car:1, van:5, cat:9999}
Object.keys(js).map( x => ({type: x, value: js[x] }) )
[ { type: 'car', value: 1 },
{ type: 'van', value: 5 },
{ type: 'cat', value: 9999 } ]
I'm trying to create a new object (newobj) with new keys and props from a poorly structured existing array of object (arrays?) ex.
[{"product":["1009", "name", "price", "image", "description"]},
{"product":["1004", "name2", "price2", "image2", "description2"]}]
I'm getting result I want but newobj does not update outside of the scope of the forEach method (more than 1 result). My question is what am I not getting ? Is forEach incorrect method with this type obj?
var newobj = {};
Object.keys(oldobj).forEach(function(prop) {
newobj["id"] = Number(oldobj[prop]["product"][0]),
newobj["name"] = oldobj[prop]["product"][1],
newobj["price"] = Number(oldobj[prop]["product"][3]),
newobj["image"] = "url" + oldobj[prop]["product"][0] + ".jpg",
newobj["description"] = oldobj[prop]["product"][2];
// this works
// console.log(JSON.stringify(newobj));
});
// this only updated with one
app.locals.newobj = newobj;
I've also tried mapping (w/ underscore) but I have the same result, I can't access outside scope.
_.each(mappedobj, function(prop) {
_.each(prop["product"][0], function(vals){
newobj["id"] = Number(prop["product"][0]);
console.log(JSON.stringify(newobj));
});
});
If you want all the values from the old object, you need to make newobj an array of objects. You can use .map() to do this transformation.
Object and array destructuring is a convenient way to avoid all those hard-coded indexes. And by naming the parameter variables properly, you can use object literal shorthand to create the resulting objects more easily.
var oldobj = [{
"product": ["1009", "name", "price", "image", "description"]
},
{
"product": ["1004", "name2", "price2", "image2", "description2"]
}
];
var newobj = oldobj.map(({product: [id, name, price, url, description]}) =>
({id: Number(id), name, price: Number(price), url: `url${url}.jpg`, description})
);
console.log(newobj);
Try this
let newObject = _.map(oldObject, (item) => {
return {
id: item.product[0],
name: item.product[1],
price: item.product[2],
image: item.product[3],
description: item.product[4]
};
});
If you want to convert an array of poorly structured object to an array of well structured ones, you can use Array.prototype.map from VanillaJS:
const data = [
{"product": ["1009", "name", "120", "image", "description"]},
{"product": ["1004", "name2", "250", "image2", "description2"]},
{"product": ["1012", "name3", "85", "image3", "description3"]}
];
const products = data.map(({ product }) => {
const [id, name, price, image, description] = product;
return {
id: Number(id),
name,
price: Number(price),
image: `url${image}.jpg`,
description
};
});
console.log(products);