I have an array of objects, where inside each object I have another array. I need to access the object inside that array. How do I do that?
As an example, here is my function where I log into the console each one of those arrays. And I want to console log each description instead.
const var = data.filter((u) => {
console.log(u.array)
})
And here is the JSON data
[
{
"agreed": true,
"email": "test#test.com"
"array": [
{
"name": "Alex",
"city": "Pedro",
"state": "WA",
"description": "Alex was very patient. He is one of the good guys!"
}
]
}
]
Here is the code snippet. data contains the original array then u contains each object of outer array. Then u.array.map traverses each individual array and i.description contains each sub-array's description.
data.map((u) => {
u.array.map((i) => {
console.log(i.description);
}
})
if you know the exact index, you can do this.
const var = data.filter((u) => {
console.log(u.array[0].description)
})
if you dont know the exact index, or if you wanna do this for each item in the array you can do this.
const var = data.filter((u) => {
u.array.forEach(item => {
console.log(item.description)
})
})
Well,
if this would be the structure of your Javascript Object
var data =
[
{
"agreed": true,
"email": "test#test.com"
"array": [
{
"name": "Alex",
"city": "Pedro",
"state": "WA",
"description": "Alex was very patient. He is one of the good guys!"
}
]
}
]
Then You can access the array by,
data[0].array[0].name;
And you can console.log description like this, if you are using jquery
$.each(data[0].array, function(i,v){
console.log(v.description);
})
You index into arrays with array[someIndex] starting with 0 for the first item.
So you can:
let arr = [{
"agreed": true,
"email": "test#test.com",
"array": [{
"name": "Alex",
"city": "Pedro",
"state": "WA",
"description": "Alex was very patient. He is one of the good guys!"
}]
}]
// get the first whole object
console.log(arr[0])
// get the arra property of the first object
console.log(arr[0].array)
// get the first object of that array
console.log(arr[0].array[0])
// get a property on that object
console.log(arr[0].array[0].name)
If you need to dig into an array and access of manipulate values, you can use tools like forEach, reduce(), etc. to loop over them:
let arr = [{"agreed": true,"email": "test#test.com","array": [{"name": "Alex","city": "Pedro","state": "WA","description": "Alex was very patient. He is one of the good guys!"},{"name": "Mark","city": "Anchorage","state": "AK","description": "Mark is also patient. He is one of the good guys!"}]},{"agreed": true,"email": "test#test.com","array": [{"name": "Steve","city": "New York","state": "NY","description": "Steve was very patient. He is one of the good guys!"},{"name": "Nancy","city": "Anchorage","state": "AK","description": "Nancy is also patient. She is awesome!"}]}]
// log each name
arr.forEach(obj => {
obj.array.forEach(item => {
console.log(item.name)
})
})
// build a new list of just the cities
let cities = arr.reduce((arr, obj) => {
obj.array.forEach(item => {
arr.push(item.city)
})
return arr
}, [])
console.log(cities)
You can save all descriptions to an array or just display it, like this
let descriptions = [];
data.map(item => item.array)
.forEach(array => {
array.forEach(obj => {
console.log(obj.description);
descriptions.push(obj.description);
});
});
console.log(descriptions);
Related
I have an object like this:
const objBefore:
{
"id": "3pa99f64-5717-4562-b3fc-2c963f66afa1",
"number": "5000",
"enabled": true,
"classes": [
{
"id": "2fc87f64-5417-4562-b3fc-2c963f66afa4",
"name": "General"
},
{
"id": "7ffcada8-0215-4fb0-bea9-2266836d3b18",
"name": "Special"
},
{
"id": "6ee973f7-c77b-4738-b275-9a7299b9b82b",
"name": "Limited"
}
]
}
Using es6, I want to grab everything in the object except the name key of the inner classes array to pass it to an api.
So:
{
"id": "3pa99f64-5717-4562-b3fc-2c963f66afa1",
"number": "5000",
"enabled": true,
"classes": [
{"id": "2fc87f64-5417-4562-b3fc-2c963f66afa4"},
{"id": "7ffcada8-0215-4fb0-bea9-2266836d3b18"},
{"id": "6ee973f7-c77b-4738-b275-9a7299b9b82b"}
]
}
The closest I got was: let {id, number, enabled, classes: [{id}]} = objBefore;
But it only gets me one id in classes. I've tried spreading above using [...{id}] or [{...id}]. Same thing.
I find it challenging to get the right mental model for how to think about this when it's on multiple levels. In my mind, when I say [...{id}] I'm thinking, "I want the id property as an object in the outer classes array, but give me every id in the array!"
Clearly I'm not thinking about this correctly.
I've tried it using map to get that part but I'm still having trouble combining it back to the original to produce the desired result. for example:
let classIds = objBefore.classes.map(({id}) => {
return {
id
}
})
(Using the map syntax, how can I destructure in the function the other keys that are one level higher?)
To combine them I started trying anything and everything, :
let {id, number, enabled, classIds} = {objBefore, [...classIds]} // returns undefined for all
I'd prefer to do it in one statement. But if that's not possible, then what's a clean way to do it using map?.
You can't destructure and map at the same time in the way you're looking to do it. The main purpose of destructuring assignment is to extract data from an array/object and not for manipulating data. In your case, as you're after an object with the same keys/value as your original object, just with a different classes array, I would instead suggest creating a new object and spreading ... the original object into that. Then you can overwrite the classes array with a mapped version of that array:
const objBefore = { "id": "3pa99f64-5717-4562-b3fc-2c963f66afa1", "number": "5000", "enabled": true, "classes": [ { "id": "2fc87f64-5417-4562-b3fc-2c963f66afa4", "name": "General" }, { "id": "7ffcada8-0215-4fb0-bea9-2266836d3b18", "name": "Special" }, { "id": "6ee973f7-c77b-4738-b275-9a7299b9b82b", "name": "Limited" } ] };
const newObj = {
...objBefore,
classes: objBefore.classes.map(({id}) => ({id}))
};
console.log(newObj);
How about using simple util method with object destructuring, spread operator and map
const objBefore = {
id: "3pa99f64-5717-4562-b3fc-2c963f66afa1",
number: "5000",
enabled: true,
classes: [
{
id: "2fc87f64-5417-4562-b3fc-2c963f66afa4",
name: "General",
},
{
id: "7ffcada8-0215-4fb0-bea9-2266836d3b18",
name: "Special",
},
{
id: "6ee973f7-c77b-4738-b275-9a7299b9b82b",
name: "Limited",
},
],
};
const process = ({ classes, ...rest }) => ({
...rest,
classes: classes.map(({ id }) => ({ id })),
});
console.log(process(objBefore))
In one line, you could do this:
const objAfter = { ...objBefore, classes: objBefore.classes.map(item => ({ id: item.id })) };
Or, if you prefer:
const objAfter = {...objBefore, classes: objBefore.classes.map(({id}) => ({id}))};
There isn't any way in object destructing to copy an entire array of objects into a different array of objects by removing properties so you use .map() for that.
I have the following object below with multiple arrays.
{
"services": [
{
"id": "100",
"name": "PIX"
},
{
"id": "200",
"name": "Rendimentos"
}
],
"channels": [
{
"id": "300",
"name": "Chat"
}
]
}
The idea is to generate query strings, something like that.
services=100&services=200&channels=300
I know you can do it with map and join, but I would know if it was with a pure object, now this format below, I'm confused
You can use URLSearchParams() API.
Iterate your data and append key/value pairs or map an entries array to pass to the constructor
I have no idea what determines the expected output you have shown from the data displayed so am using a simpler data structure for demonstration purposes.
You can combine with URL() API to create full url string as shown below also
const data = [
{name:'foo', value:10},
{name:'bar', value:20}
]
// Loop and append key/values
const params = new URLSearchParams();
data.forEach(e => params.append(e.name, e.value));
console.log('params:', params.toString());
// Alternate approach passing entries array to constructor
const params2 = new URLSearchParams(data.map(e => [e.name,e.value]));
console.log('params2:',params2.toString())
//Adding to a URL
const url = new URL('http://example.com')
url.search = params
console.log('Full url:',url)
Using the updated array data in question:
const data={services:[{id:"100",name:"PIX"},{id:"200",name:"Rendimentos"}],channels:[{id:"300",name:"Chat"}]};
const entries = [];
Object.entries(data).forEach(([k,arr])=> arr.forEach(({id}) => entries.push([k,id])));
const params = new URLSearchParams(entries);
const url = new URL('http://example.com')
url.search = params;
console.log(url)
Looks like you're hung up on trying to iterate an object with map() or join(), which you can't do directly. Instead you can use Object.entries to convert the object into an array and iterate that. Since there is a nested map() you can flat() it before join()
let obj = {
"services": [{
"id": "100",
"name": "PIX"
},
{
"id": "200",
"name": "Rendimentos"
}
],
"channels": [{
"id": "300",
"name": "Chat"
}]
}
let queryString = Object.entries(obj).map(s => s[1].map(e => `${s[0]}=${e.id}`)).flat().join('&')
console.log(queryString)
const aboutMe = [{
"name": "frank",
"about": [{
"mood": "happy",
"dinner": [{
"first": "desert",
"last": "noodles"
}]
},
{
"mood": "happy",
"dinner": [{
"first": "desert",
"last": "noodles"
}]
},
{
"mood": "happy",
"dinner": []
}
]
}]
const AllBreak = aboutMe.about.map((dinner) => ((dinner.first, dinner.last)));
const expectedOutput =["first": "desert", "last": "noodles", "first": "desert", "last": "noodles"]
console.log(aboutMe, AllBreak, expectedOutput)
so am trying to filter through a nested array learning from a tutorial I don't know why it returns cannot read property of map why is that pretty sure i filtered correctly according to the tutorial
Firstly, aboutMe is an array with an object that has an about property in it. So, if you want to access this property, you need to first access the first element of the array and then access the about property in it.
Secondly, (dinner.first, dinner.second) doesn't actually make any sense here.
Because when you have multiple expressions separated by commas in a bracket, each of those expressions get evaluated but only the last one is returned. So, here returning (dinner.first, dinner.second) is equivalent to returning dinner.second.
So, if you only want dinner.second then just return that or put them in an array (or object) and return that.
Also, since in your example it seems that it is not guaranteed that the dinner array would always have an object inside it, it is best to use Optional Chaining here.
Please have look at the solution below:
const
aboutMe = [{name:"frank",about:[{mood:"happy",dinner:[{first:"desert",last:"noodles"}]},{mood:"happy",dinner:[{first:"desert",last:"noodles"}]},{mood:"happy",dinner:[]}]}],
res = aboutMe[0].about.map(({dinner}) => [dinner?.[0]?.first, dinner?.[0]?.last])
console.log(res);
aboutMe is an array, if you want to get the property of the first element, you can use indexing [0]
const AllBreak = aboutMe[0].about.map(() => ...);
I am trying to extract "animal" and "fish" hashtags from the JSON object below. I know how to extract the first instance named "animal", but I have no idea how to extract both instances. I was thinking to use a loop, but unsure where to start with it. Please advise.
data = '{"hashtags":[{"text":"animal","indices":[5110,1521]},
{"text":"Fish","indices":[122,142]}],"symbols":[],"user_mentions":
[{"screen_name":"test241","name":"Test
Dude","id":4999095,"id_str":"489996095","indices":[30,1111]},
{"screen_name":"test","name":"test","id":11999991,
"id_str":"1999990", "indices":[11,11]}],"urls":[]}';
function showHashtag(data){
i = 0;
obj = JSON.parse(data);
console.log(obj.hashtags[i].text);
}
showHashtag(data);
Use Array.prototype.filter():
let data = '{"hashtags":[{"text":"animal","indices":[5110,1521]},{"text":"Fish","indices":[122,142]}],"symbols":[],"user_mentions":[{"screen_name":"test241","name":"Test Dude","id":4999095,"id_str":"489996095","indices":[30,1111]}, {"screen_name":"test","name":"test","id":11999991, "id_str":"1999990", "indices":[11,11]}],"urls":[]}';
function showHashtag(data){
return JSON.parse(data).hashtags.filter(e => /animal|fish/i.test(e.text))
}
console.log(showHashtag(data));
To make the function reusable, in case you want to find other "hashtags", you could pass an array like so:
function showHashtag(data, tags){
let r = new RegExp(tags.join("|"), "i");
return JSON.parse(data).hashtags.filter(e => r.test(e.text))
}
console.log(showHashtag(data, ['animal', 'fish']));
To get only the text property, just chain map()
console.log(showHashtag(data, ['animal', 'fish']).map(e => e.text));
or in the function
return JSON.parse(data).hashtags
.filter(e => /animal|fish/i.test(e.text))
.map(e => e.text);
EDIT:
I don't really get why you would filter by animal and fish if all you want is an array with ['animal', 'fish']. To only get the objects that have a text property, again, use filter, but like this
let data = '{"hashtags":[{"text":"animal","indices":[5110,1521]},{"text":"Fish","indices":[122,142]}],"symbols":[],"user_mentions":[{"screen_name":"test241","name":"Test Dude","id":4999095,"id_str":"489996095","indices":[30,1111]}, {"screen_name":"test","name":"test","id":11999991, "id_str":"1999990", "indices":[11,11]}],"urls":[]}';
function showHashtag(data){
return JSON.parse(data).hashtags
.filter(e => e.text)
.map(e => e.text);
}
console.log(showHashtag(data));
For me, Lodash can be of great use here, which have different functions in terms of collections. For your case i'd use _.find function to help check the array and get any of the tags with the creteria passed in as second argument like so:
.find(collection, [predicate=.identity], [fromIndex=0])
source npm package
Iterates over elements of collection, returning the first element
predicate returns truthy for. The predicate is invoked with three
arguments: (value, index|key, collection).
with your case this should work
var data = '{ "hashtags": [ { "text": "animal", "indices": [ 5110, 1521 ] }, { "text": "Fish", "indices": [ 122, 142 ] } ], "symbols": [], "user_mentions": [ { "screen_name": "test241", "name": "Test \n Dude", "id": 4999095, "id_str": "489996095", "indices": [ 30, 1111 ] }, { "screen_name": "test", "name": "test", "id": 11999991, "id_str": "1999990", "indices": [ 11, 11 ] } ], "urls": [] }';
var obj = JSON.parse(data);
_.find(obj.hashtags, { 'text': 'animal' });
// => { "text": "animal", "indices": [ 5110, 1521 ] }
For simple parsing like this one, I would use the plain old obj.forEach() method, it is more readable and easy to understand, especially for javascript beginner.
obj = JSON.parse(data).hashtags;
obj.forEach(function(element) {
console.log(element['text']);
});
I'm learning Immutable.js. I have an object that when called:
myObj.get('people')
returns the following:
[
{
"name": "John Stevenson",
"country": "Sweden"
},
{
"name": "John Silva",
"country": "Colombia"
},
{
"name": "John Van der Bier",
"country": "Holland"
},
{
"name": "John McDonald",
"country": "Scotland"
}
]
I'm trying to get inside this object so I can only see country:
myObj.getIn(['people', 'country']) // undefined
What am I missing?
The problem with you're code is that the result of getIn(['people', 'country']) is attempting to access the country property of people, which is an array and doesn't have a property named country. It seems like want to loop over people and build an array of their countries, which you can do with map:
var countries = myObj.get('people').map(person => {
return person.country
})
The previous answer will return an array. If you are truly wanting to use Immutable you should use
import { fromJS } from 'Immutable';
const immutableObj = fromJS(myObj);
//map() or forEach() here
var countries = immutableObj.map(person => {
return person.get('country');
})