How to get data from a complicated object / array structure? - javascript

I'm trying to get data from a complicated API structure. How would I get all the image from the following objects and arrays:
const x = { cars: [
{ types:
{
name: "VW",
image: [{ url: "http://www.lkjl.com" }]
}
},
{...},
{...}
]};
I know I can get the image url like this:
x.cars[0].types.image[0].url
But how can I print out all the image urls?
x.cars.map(item => {
return(
item.image[0].url; // this is wrong
);
});
Do I need to have another map inside the map function?

You could use Array#reduce with mapping the url property.
const
x = { cars: [{ types: { name: "VW", image: [{ url: "http://www.lkjl.com" },{ url: "http://www.alkjl.com" }] } }, { types: { name: "Tata", image: [{ url: "http://www.lskal.com" },{ url: "http://www.lkfjl.com" }] } }] },
images = x.cars.reduce((r, item) => r.concat(item.types.image.map(i => i.url)), []);
console.log(images);

Within the cars array you have image array inside the types object, So you have to iterate over both the arrays to print out all the images.
See the code below.
const x = { cars: [
{ types:
{
name: "VW",
image: [{ url: "http://www.lkjl.com" }]
}
},
{ types:
{
name: "VW",
image: [{ url: "http://www.lkjl12.com" }]
}
}
]};
x.cars.forEach(car => {
car.types.image.forEach( i => console.log(i.url));
})

i think you missed to access the 'types' object in your map function
it should be like this :
x.cars.map(item => {
return(
item.types.image[0].url; //this should work for you
);
});

x.cars.map(item => item.types.image[0].url)

I think you missed types:
x.cars.map(item => {
return(
item.types.image[0].url;
);
});

have you try this way ?
x.cars.map((item, key) => {
return(
item.types.image[0].url;
//you're missing 'types'
);
});
i hope it can help you.

Related

Return all values of nested arrays using string identifier

Given an object searchable, is there a simple way of returning all the id values using lodash or underscore.js (or equivalent) where I can define the path to id?
const searchable = {
things: [
{
id: 'thing-id-one',
properties: [
{ id: 'd1-i1' },
{ id: 'd1-i2' },
]
},
{
id: 'thing-id-two',
properties: [
{ id: 'd2-i1' },
{ id: 'd2-i2' },
]
}
]
}
I am looking to see if this is possible in a manner similar to how we can use lodash.get e.g. if we wanted to return the things array from searchable we could do
const things = _.get(searchable, 'things');
I can't seem to find anything similar in the documentation. I am looking for something
that could contain an implementation similar to:
_.<some_function>(searchable, 'things[].properties[].id')
Note: I am well aware of functions like Array.map etc and there are numerous ways of extracting the id property - it is this specific use case that I am trying to figure out, what library could support passing a path as a string like above or does lodash/underscore support such a method.
Found a solution using the package jsonpath
const jp = require('jsonpath');
const result = jp.query(searchable, '$.things[*].properties[*].id')
console.log(result);
// outputs: [ 'd1-i1', 'd1-i2', 'd2-i1', 'd2-i2' ]
you can do it easily in plain js
like this
const searchable = {
things: [
{
id: 'thing-id-one',
properties: [
{ id: 'd1-i1' },
{ id: 'd1-i2' },
]
},
{
id: 'thing-id-two',
properties: [
{ id: 'd2-i1' },
{ id: 'd2-i2' },
]
}
]
}
const search = (data, k) => {
if(typeof data !== 'object'){
return []
}
return Object.entries(data).flatMap(([key, value]) => key === k ? [value]: search(value, k))
}
console.log(search(searchable, 'id'))
_.map and _.flatten together with iteratee shorthands let you expand nested properties. Every time you need to expand into an array, just chain another map and flatten:
const searchable = {
things: [
{
id: 'thing-id-one',
properties: [
{ id: 'd1-i1' },
{ id: 'd1-i2' },
]
},
{
id: 'thing-id-two',
properties: [
{ id: 'd2-i1' },
{ id: 'd2-i2' },
]
}
]
}
// Let's say the path is "things[].properties[].id"
const result = _.chain(searchable)
.get('things').map('properties').flatten()
.map('id').value();
console.log(result);
<script src="https://cdn.jsdelivr.net/npm/underscore#1.13.4/underscore-umd-min.js"></script>

Object gets duplicated inside array

This is the result I want to achieve
dataset: [
dataset: [
{
seriesname: "",
data: [
{
value: "123",
},
{
value: "123",
},
]
},
]
]
My problem right now is that the second dataset gets duplicated.
This is how I am setting it (val is an integer and allYears is an array of integers):
this.grphColumn.dataSource.dataset[0].dataset = this.allYears.map(el => {
return {
seriesname: "Planned",
data: [{value: val}, {value: val}]
}
});
How can I make it so the dataset doesn't get duplicated?
You have to map the values separately, if you dont want the seriesName to be Repeated..
const yearsMap = this.allYears.map((el) => { return { value: el } });
this.grphColumn.dataSource.dataset[0].dataset = {
seriesname: "Planned",
data: yearsMap
}

I think a better knowledge of javascript array methods will help me?

I'm trying to update an array of products in a custom mutation in keystone-next. I have got as far as the below, which works for the first product in my array. Obviously this only works if there is only 1 item in the array.
I know I need to map through the array in some way but I can't get my head round it.
const productIds = user.cart.map((cartItem) => cartItem.product.id);
console.log(productIds)
await context.lists.Product.updateMany({
// this is the bit that's wrong
data: [
{
id: productIds[0],
data: {
status: 'PENDING',
},
},
],
});
Yes, you need to map through your array of productIds
const productIds = user.cart.map((cartItem) => cartItem.product.id);
productIds.map(async (id) => {
await context.lists.Product.updateMany({
data: [
{
id,
data: {
status: 'PENDING',
},
},
],
});
})
But most efficiently you should handle the update in the first map without getting the array of productIds first. Like this
user.cart.map(async(cartItem) => {
await context.lists.Product.updateMany({
data: [
{
id: cartItem.product.id,
data: {
status: 'PENDING',
},
},
],
});
});
Something like this u mean?
const productIds = user.cart.map((cartItem) => cartItem.product.id);
console.log(productIds)
await context.lists.Product.updateMany({
data: productIds.map(productId => ({
id: productId,
data: {
status: 'PENDING',
},
}))
});

Omitting one or multiple values in javascript using lodash

I have a complex structure and I want to omit some properties from this structure for final value
let ListofWorlds = {
listOfCountries: [{
add: [{
id: 1,
updated: {
areacode: 123,
city: {
city: {'Austrailia'},
houses: {1000}
}
}
}], remove: []
}]
}
I want to omit city property from this structure and need this
let ListofWorlds = {
listOfCountries: [{
add: [{
id: 1,
updated: {
areacode: 123
}
}], remove: []
}]
}
This is what I have tried
let newListOfWorls = _.map(ListofWorlds, function (worlds) {
return _.omit(worlds, ['city']); })
Appreciate the help and knowledge
This is what i have tried.
let ListofWorlds = {
listOfCountries: [{
add: [{
id: 1,
updated: {
areacode: 123,
city: {
city: 'Austrailia',
houses: 1000
}
}
}], remove: []
}]}
const newList = ListofWorlds.listOfCountries.map(arr=>{
arr.add.forEach((item,index)=>{
arr.add[index] = _.omit(item,'updated.city')
})
return arr
})
Probably not the best way to do it, but hey it works, and why your code doesn't work probably you mapped an Object ListofWorlds and you need to be specific which field you want to be omitted

Declaring dynamic keys in json (javascript, node)

I have an array of objects, each object is similar to:
{ word: 'intentional',
definition: 'done by intention or design',
type: 'adjective',
Synonyms: [ 'conscious', 'deliberate', 'intended', 'knowing', ] }
I am trying to convert the whole array into following json format:
{
"conscious": {
"data": ["done by intention or design"],
"type": "adjective",
"Synonym For": ["intentional"]
},
"deliberate": {
"data": ["done by intention or design"],
"type": "adjective",
"Synonym For": ["intentional"]
},
...
}
This json format is an input to another program, which I do not control.
I am running it on node.js.
How can I declare an object and then loop through the array to fill it as intended?
var obj = { word: 'intentional',
definition: 'done by intention or design',
type: 'adjective',
Synonyms: [ 'conscious', 'deliberate', 'intended', 'knowing' ] },
res = obj.Synonyms.reduce(function(s,a) {
s[a] = { data: [obj.definition], type: obj.type, SynonymFor: [obj.word] };
return s;
}, {});
console.log(res);
var jsonObj = {};
wordArray.forEach((word) => {
word.Synonyms.forEach((synonym) => {
jsonObj[synonym] = {
data: [word.definition],
type: word.type,
'Synonym For': [word.word]
};
})
})

Categories

Resources