How to include a loop within object creation? - javascript

I am trying to create an object to use in various places of HTML. It goes a little something like this:
MovieInfo = {
title: Movie.value[0].title,
meta: [
{
name: "description",
content: Movie.value[0].description,
},
{
name: "date",
content: Movie.value[0].releasedate
},
// Try to add objects from another array
Movie.value[1].forEach(function (Cast, index) {
return {
key: Cast.actorname, property: "article:tag", content: Cast.actorname
}
})
]
}
The above does not work. However if I push to the meta array after creating the MovieInfo object then it does work, like so:
MovieInfo = {
title: Movie.value[0].title,
meta: [
{
name: "description",
content: Movie.value[0].description,
},
{
name: "date",
content: Movie.value[0].releasedate
},
]
}
// Try to add objects from another array
Movie.value[1].forEach(function (Cast, index) {
MovieInfo.meta.push({
key: Cast.actorname, property: "article:tag", content: Cast.actorname
})
})
I have to do quite a few of these loops in different areas so I would prefer them to be done while creating MovieInfo than outside of it. Is that possible? That is, is it possible to make my first attempt work by having a loop inside the object creation itself?

You can use an IIFE to do arbitrary things in an object literal (or really, any expression):
const MovieInfo = {
title: Movie.value[0].title,
meta: (() => {
const meta = [
{
name: "description",
content: Movie.value[0].description,
},
{
name: "date",
content: Movie.value[0].releasedate
},
];
for (const cast of Movie.value[1]) {
meta.push({
key: cast.actorname,
property: "article:tag",
content: cast.actorname
});
}
return meta;
})(),
};
In this case, I would however recommend to simply build the array using concat and map:
const MovieInfo = {
title: Movie.value[0].title,
meta: [
{
name: "description",
content: Movie.value[0].description,
},
{
name: "date",
content: Movie.value[0].releasedate
},
].concat(Movie.value[1].map(cast => ({
key: cast.actorname,
property: "article:tag",
content: cast.actorname
}))),
};

Related

How to limit an array field in javascript object to a certain length

I know this may a simple problem but I have a the following javascript object:
const categories = {
title: 'cat1',
contents: [
{
name: 'cont1'
},
{
name: 'cont2'
},
{
name: 'cont3'
}
]
}
How can a transform this categories object so it has only 2 contents element as an example?
const transformedCategories = {
title: 'cat1',
contents: [
{
name: 'cont1'
},
{
name: 'cont2'
}
]
}
A couple of ways to do it:
const transformedCategories = {
title: categories.title,
contents: categories.contents.slice(0,2) // you can also use splice here
}
Another, slightly cheeky way:
const contents = [...categories.contents];
contents.length = 2;
const transformedCategories = {...categories, contents}

How to return a new array of object from object nested props with reduce in JavaScript

I'm trying to return a new array of objects from the nested properties of another object. This is my current object:
const teams = {
GRYFFINDOR: {
display: 'Gryffindor',
channel: ['#team-gryffindor'],
ui: 'lion',
},
HUFFLEPLUFF: {
display: 'Hufflepuff',
channel: ['#team-hufflepuff'],
ui: '', // empty string on purpose
},
SLYTHERIN: {
display: 'Slytherin',
channel: ['#team-slytherin'],
ui: 'snake',
},
}
Now, I'm trying to return an array of objects like so:
[
{ value: 'lion' },
{ value: '' },
{ value: 'snake' },
]
This is what I have tried:
const teamsUI = [Object.keys(teams).reduce((carry, item) => {
return {...carry, ...{ ['value']: teams[item].ui }}
}, {})];;
However, I get this:
console.log(teamsUI); // returns [ { value: 'snake' }]
What am I doing wrong?
You could do like this:
const teams = {
GRYFFINDOR: {
display: 'Gryffindor',
channel: ['#team-gryffindor'],
ui: 'lion',
},
HUFFLEPLUFF: {
display: 'Hufflepuff',
channel: ['#team-hufflepuff'],
ui: '', // empty string on purpose
},
SLYTHERIN: {
display: 'Slytherin',
channel: ['#team-slytherin'],
ui: 'snake',
},
}
const result = Object.values(teams).map(({ ui }) => ({ value: ui }));
console.log(result);
Beside nested result structure, you could take the values and destructure the wanted property formapping.
const
teams = { GRYFFINDOR: { display: 'Gryffindor', channel: ['#team-gryffindor'], ui: 'lion' }, HUFFLEPLUFF: { display: 'Hufflepuff', channel: ['#team-hufflepuff'], ui: '' }, SLYTHERIN: { display: 'Slytherin', channel: ['#team-slytherin'], ui: 'snake' } },
result = Object.values(teams).map(({ ui: value }) => ({ value }));
console.log(result);
Here is the shortest way to achieve what you want
Object.keys(teams).map(t=>({value: teams[t].ui}))
Now what are you doing wrong?
Take a look at this part
Object.keys(teams).reduce((carry, item) => {
return {...carry, ...{ ['value']: teams[item].ui }}
}, {});
You're reducing your object to a single value with the same key called value. This means that the value of teams[item].ui of the current object in the reduce function will override the previous and hence you'll end up with the last object of that reduce function. You're finally wrapping this last object in an array which gives you what you have.
A better way to achieve that will be to do something like this
Object.keys(teams).reduce((carry, item, index)=>{
carry[index] = { value: teams[item].ui };
return carry;
}, []);

Javascript - transforming an object of array list to new formated one?

I'm trying to transform an object contain array to another one with javascript. Below is an example of the object field and what the formatted one should look like.
let Fields = {
GAME: [
{ code: '{{PES}}', title: { en: "playPES"} },
{ code: '{{FIFA}}', title: { en: "playFIFA " } },
]
};
I need The new Fields to looks like this
let newFields = {
name: 'GAME',
tags:[
{ name: 'playPES', value: "{{PES}}" },
{ name: 'playFIFA', value: "{{FIFA}}" }
]},
One contributor suggested me a method like this but i think something need to modify in it but couldn't figure it out.
export const transform = (fields) => ({
tags: Object .entries (fields) .map (([name, innerFields]) => ({
name,
tags: innerFields.map(({code, title: title: {en})=>({name: en, value: code}))
}))
});
// newFields= transform(Fields)
I'm new working with javascript so any help is greatly appreciated, Thanks.
const transform = (o) => {
return Object.entries(o).map((e)=>({
name: e[0],
tags: e[1].map((k)=>({name: (k.title)?k.title.en:undefined, value: k.code}))
}))[0]
}
console.log(transform({
GAME: [
{ code: '{{PES}}', title: { en: "playPES"} },
{ code: '{{FIFA}}', title: { en: "playFIFA " } },
]
}))
Using the entries method you posted:
let Fields = {
GAME: [
{ code: '{{PES}}', title: { en: "playPES"} },
{ code: '{{FIFA}}', title: { en: "playFIFA " } },
]
};
// 1. Obtain keys and values from first object
Fields = Object.entries(oldFields);
// 2. Create new object
const newFields = {};
// 3. Create the name key value pair from new Fields array
newFields.name = Fields[0][0];
// 4. Create the tags key value pair by mapping the subarray in the new Fields array
newFields.tags = Fields[0][1].map(entry => ({ name: entry.title.en, value: entry.code }));
Object.entries(Fields) will return this:
[
"GAME",
[TagsArray]
]
And Object.entries(Fields).map will be mapping this values.
The first map, will receive only GAME, and not an array.
Change the code to something like this:
export const transform = (Fields) => {
const [name, tags] = Object.entries(Fields);
return {
name,
tags: tags.map(({ code, title }) => ({
name: title.en,
value: code
}))
}
}
Hope it help :)
let Fields = {
GAME: [
{ code: '{{PES}}', title: { en: "playPES"} },
{ code: '{{FIFA}}', title: { en: "playFIFA " } },
]
};
let newFields = {
name: 'GAME',
tags:[
{ name: 'playPES', value: "{{PES}}" },
{ name: 'playFIFA', value: "{{FIFA}}" }
]
}
let answer = {
name: "Game",
tags: [
]
}
Fields.GAME.map(i => {
var JSON = {
"name": i.title.en,
"value": i.code
}
answer.tags.push(JSON);
});
console.log(answer);
I think that this is more readable, but not easier... If you want the result as object you need to use reduce, because when you do this
Object.keys(Fields)
Your object transform to array, but reduce can change array to object back.
let Fields = {
GAME: [
{ code: '{{PES}}', title: { en: "playPES"} },
{ code: '{{FIFA}}', title: { en: "playFIFA " } },
]
};
const result = Object.keys(Fields).reduce((acc, rec) => {
return {
name: rec,
tags: Fields[rec].map(el => {
return {
name: el.title.en,
value: el.code
}
})
}
}, {})
console.log(result)
let Fields = {
GAME: [
{ code: '{{PES}}', title: { en: "playPES"} },
{ code: '{{FIFA}}', title: { en: "playFIFA " } },
]
};
const transform = (fields) => ({
tags: Object .entries (fields) .map (([name, innerFields]) => ({
name,
tags: innerFields.map(({code, title: title,en})=>({name: title.en, value: code}))
}))
});
//check required output in console
console.log(transform(Fields));

Create a key map for all paths in a recursive/nested object array

I have an n levels deep nested array of tag objects with title and ID. What I'm trying to create is a an object with IDs as keys and values being an array describing the title-path to that ID.
I'm no master at recursion so my attempt below doesn't exactly provide the result I need.
Here's the original nested tag array:
const tags = [
{
title: 'Wood',
id: 'dkgkeixn',
tags: [
{
title: 'Material',
id: 'ewyherer'
},
{
title: 'Construction',
id: 'cchtfyjf'
}
]
},
{
title: 'Steel',
id: 'drftgycs',
tags: [
{
title: 'Surface',
id: 'sfkstewc',
tags: [
{
title: 'Polished',
id: 'vbraurff'
},
{
title: 'Coated',
id: 'sdusfgsf'
}
]
},
{
title: 'Quality',
id: 'zsasyewe'
}
]
}
]
The output I'm trying to get is this:
{
'dkgkeixn': ['Wood'],
'ewyherer': ['Wood', 'Material'],
'cchtfyjf': ['Wood', 'Construction'],
'drftgycs': ['Steel'],
'sfkstewc': ['Steel', 'Surface'],
'vbraurff': ['Steel', 'Surface', 'Polished'],
'sdusfgsf': ['Steel', 'Surface', 'Coated'],
'zsasyewe': ['Steel', 'Quality']
}
So I'm building this recursive function which is almost doing it's job, but I keep getting the wrong paths in my flat/key map:
function flatMap(tag, acc, pathBefore) {
if (!acc[tag.id]) acc[tag.id] = [...pathBefore];
acc[tag.id].push(tag.title);
if (tag.tags) {
pathBefore.push(tag.title)
tag.tags.forEach(el => flatMap(el, acc, pathBefore))
}
return acc
}
const keyMap = flatMap({ title: 'Root', id: 'root', tags}, {}, []);
console.log("keyMap", keyMap)
I'm trying to get the path until a tag with no tags and then set that path as value for the ID and then push the items 'own' title. But somehow the paths get messed up.
Check this, makePaths arguments are tags, result object and prefixed titles.
const makePaths = (tags, res = {}, prefix = []) => {
tags.forEach(tag => {
const values = [...prefix, tag.title];
Object.assign(res, { [tag.id]: values });
if (tag.tags) {
makePaths(tag.tags, res, values);
}
});
return res;
};
const tags = [
{
title: "Wood",
id: "dkgkeixn",
tags: [
{
title: "Material",
id: "ewyherer"
},
{
title: "Construction",
id: "cchtfyjf"
}
]
},
{
title: "Steel",
id: "drftgycs",
tags: [
{
title: "Surface",
id: "sfkstewc",
tags: [
{
title: "Polished",
id: "vbraurff"
},
{
title: "Coated",
id: "sdusfgsf"
}
]
},
{
title: "Quality",
id: "zsasyewe"
}
]
}
];
console.log(makePaths(tags));

REACTJS: obj.push() and obj.concat is not a function

I am having an error that my obj.push() and obj.concat() is not a function but I am not so sure why. Here is my code:
onSearch = () => {
var obj = {
product: [
{
field: "is_published",
filter_value: 1
},
{
field: "order_mode",
filter_array: [
"fcfs",
"purchase-order"
]
},
{
relationship: "store",
filter_object: {
field: "slug",
filter_value: "sample"
}
}
]
}
if (this.state.search !== "") {
obj.push(
{
field: "name",
text_search: this.state.search
}
)
}
var obj2 = {
taxonomies: [
[
{ field: "type",
filter_value: "seller"
},
{ field: "slug",
filter_value: "brand"
}
]
]
}
var conc = obj.concat(obj2);
var { getProductSearch } = this.props
getProductSearch(obj.concat(obj2))
}
product and taxonomies are stored in different variables but I need to pass them as one array to getProductSearch and for that, I need to use concat(). then I need to use push() because I want to add an object to the array obj. What am I doing wrong?
The simple answer is because you can't push onto an object. Push is used for arrays.
To make this work you could instead change your code to push onto the array in your object by doing.
obj.product.push(
{
field: "name",
text_search: this.state.search
}
)
If you are trying to make product dynamic where there are multiple products like [fruits, veggies, meat] then you could change it simply by doing
onSearch(productName)
obj[productName].push(
{
field: "name",
text_search: this.state.search
}
)
This would let you call onSearch(veggies) and push only to that array if you set it up that way.

Categories

Resources