Access nested Immutable Map property - javascript

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');
})

Related

Add new child objects to existing object in React

I am trying to update through useState a child object with an additional object. I created an example to make this more clear :
https://codesandbox.io/s/affectionate-wescoff-u01x0?file=/src/App.js
The example object looks like :
{
"id": 123,
"books": {
"book": {}
}
}
When I push more data in I want it to look like this :
{
"id": 123,
"books": {
"book": {
"name": "Sirens of Titan",
"author": "Kurt Vonnegut"
},
"book": {
"name": "The Hobbit",
"author": "J.R.R. Tolkein"
}
}
}
At this stage I have it pretty messed up and it looks like :
{
"id":123,
"books":[
{
"0":{
"book":{
},
"sampleData1":{
"book":{
"name":"Sirens of Titan",
"author":"Kurt Vonnegut"
}
}
},
"sampleData2":{
"book":{
"name":"The Hobbit",
"author":"J.R.R. Tolkein"
}
}
}
]
}
This is the way I set that broken object :
const [main, setMain] = useState(library);
function addNestedObj() {
setMain({ ...main, books: [{ ...main.books, sampleData1 }] });
}
Just take the destructuring a stage further:
setMain({...main, kids: [...main.kids, secondObj]})
The books property of your library object was an object, not an array. This might have been necessary but I guessed that it isn't since your book objects already have a name property, so they don't need a separate key.
With that change, you can modify your setMain function to add the book property of the sampleData to the books property of your state:
setMain({ ...main, books: [...main.books, sampleData1.book] });
I've added these changes in a fork of your CodeSandbox: https://codesandbox.io/s/modest-fog-byegh?file=/src/App.js

How can I get an array within a request response object in javascript/react?

How can I get the 'address' array within of request response object below?
{
"title": "MRS.",
"name": "Aluno",
"lastName": "3",
"birthday": "2019-08-31",
"address": [
{
"addressName": "rua 2",
"zipCode": "13901264",
"city": "amparo",
"state": "sp",
"country": "brasil"
},
{
"addressName": "rua 2",
"zipCode": "13901264",
"city": "amparo",
"state": "sp",
"country": "brasil"
},
]
}
If I save this object in a state called customer and print console.log(customer.address) it works well and I can see the address informations, but I can't use map or forEach methods like customer.address.forEach, I receive an error :(
You can use methods such as map, reduce, filter, forEach only on Array Not on Object.
the key address has value as an object, To read it you can simply use
console.log(customer.address.addressName) //street x
console.log(customer.address.zipCode) //13901264
If you want to loop through properties
Object.values(customer.address).forEach((value) => {
console.log(value);
})
// OR
Object.keys(customer.address).forEach((key) => {
console.log(customer.address[key]);
})
The property address it not an array, if you need to convert it into an array of one element you can use:
const valueAsArray = [response.address]
Object.keys(out.address).map(key => {
console.log(out.address[key]);
// etc ...
})

creating multiple javascript objects using a loop that reads from json data

I am trying to create a number of Javscript objects at once by using a loop through json data. I'm having trouble finding a way to do this and if someone could take a look at the below code and suggest the best way of looping through the json data and creating the objects that would be great.
// Create Test Constructor
function Test(name, age, address) {
this.name = name;
this.age = age;
this.address = address;
}
// Create Test Object
let test1 = new Test("name[0]", age[0], "address[0]");
//json data from a seperate .json file
{
"Tests": [
{
"name": "First Person",
"age": 20,
"address": "New York"
},
{
"name": "Second Person",
"age": 21,
"address": "The World"
},
{
"name": "Third Person",
"age": 22,
"address": "The Universe"
}
]
}
Thanks
If you just need plain objects:
const { Tests } = JSON.parse('//json data from a seperate .json file');
Now Tests should be an array of Test objects.

Access object inside the array which is inside the other object

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

JavaScript - Find an object among an array of objects, inside an array of objects

I'm using Vue, lodash, etc.
{
"street": {
"id": "1",
"streetName": "test",
"buildings": [
{
"id": "1",
"buildingName": "test"
}
]
}
}
I have a setup similar to this. This is a singular object, I basically have an array of these.
All I get is a building.id value.
From it, I need to be able to find the building it belongs to, and there isn't any direct list of buildings for me to access.
Currently
I'm using a nested loop to loop through each site until I find the one that has a building with that id. I don't know if I'm doing it correctly, it doesn't feel correct.
for(var i = 0; i < streets.length; i++){
for(var x = 0; x < streets[i].buildings.length;x++){
if(streets[i].buildings[x].id == '2aec6bed-8cdd-4043-9041-3db4681c6d08'){
}
}
}
Any tips? Thanks.
You can use a combination of filter and some methods, like this:
var result = streets.filter(function(s) {
return s.street.buildings.some(function(b) {
return b.id === searchedId;
});
});
Using .some() method will return true if any building of the iterated buildings has the searchedId.
Using .filter() will filter the streets array to return only street object where the call of some() method on its buildings will return true, in other words which meets the condition of having an idequal to searchedId.
Demo:
var streets = [{
"street": {
"id": "1",
"streetName": "test",
"buildings": [{
"id": "1",
"buildingName": "test"
}]
}
}, {
"street": {
"id": "1",
"streetName": "test",
"buildings": [{
"id": '2aec6bed-8cdd-4043-9041-3db4681c6d08',
"buildingName": "test"
}]
}
}];
var searchedId = '2aec6bed-8cdd-4043-9041-3db4681c6d08';
var result = streets.filter(function(s) {
return s.street.buildings.some(function(b) {
return b.id === searchedId;
});
});
console.log(result);
If you're trying to get all the buildings in all streets by a buildingId, this solves the problem:
streetsList.map(streetItem => streetItem.street.buildings.find(building => building.id === searchedBuildingId)).filter(v => v);
.filter(v => v) is for filtering out falsy values since we want a clean result here.
If there can be more than a single building in a street with the same id, then use .some instead of .find in the example.
Presumably you have a streets object that contains street objects, like:
var streets = [
street :{ ... },
street :{ ... },
...
];
So you need to step into each street and iterate over the buildings. A for loop should be fairly efficient since it can return as soon as it finds the building. I don't think any of the built-in looping methods will do that.
The code in the OP won't work, as streets[i].buildings must be streets[i].streets.buildings and if(streets[i].buildings[x].id must be if(streets[i].street.buildings[x].id.
Below is a working for loop version, there's also a version using recent Array methods which are very much slower even on a very small dataset. According to jsperf, the for loop version is about 100 times faster in Safari, 10 times faster in Firefox and 50 times faster in Chrome.
I also think the for loop code is much more readable and therefore maintainable.
var streets = [{
"street": {
"id": "1",
"streetName": "test",
"buildings": [{
"id": "1",
"buildingName": "test"
}, {
"id": "2",
"buildingName": "test"
}]
}
}, {
"street": {
"id": "2",
"streetName": "test",
"buildings": [{
"id": "3",
"buildingName": "test"
}]
}
}
];
function getBldById(data, id) {
for (var i=0, iLen=streets.length; i<iLen; i++) {
var street = streets[i].street;
for (var j=0, jLen=street.buildings.length; j<jLen; j++) {
if (street.buildings[j].id == id) {
return street.buildings[j];
}
}
}
return null;
}
console.log(getBldById(streets, '1'));
function getBldById2(data, id) {
return data.map(streetObj =>
streetObj.street.buildings.find(building =>
building.id === id)
).filter(v => v)[0];
}
console.log(getBldById2(streets, '1'));
You might be missing street property, right?
I mean it should be: streets[i].street.buildings[x].id

Categories

Resources