Bit of a rookie question & late in the day, but how do I access an array in an object? I am getting undefined & TypeError: Cannot read property 'length' of undefined. I can get the object data (Id, ElemId, etc) fine.
...
this.state = {
yfinder: [],
...
}
...then api call...
this.setState({
finder: res.Finder,
...
})
JSON:
"Finder": {
"Id": "23216245567u4",
"ElemId": "finder",
"Title": "Your Finder",
"Description": "This is a description",
"ResultsTitle": "What program or service are you looking for?",
"CategoryTitle": "Great! Select a category to continue..",
"Results": [
{
...
}
{
...
}
]
}
let finder = this.state.finder;
console.log(finder.Results);
for (var i = 0; i < finder.Results.length; i++) {
console.log(finder.Results[i]);
}
That's because initially your finder object doesn't have Results array. Try this and see if this works.
let finder = this.state.finder;
console.log(finder.Results);
const resultsLength = finder.Results ? finder.Results.length : null;
for (var i = 0; i < resultsLength; i++) {
console.log(finder.Results[i]);
}
You can simply use . operator to access the key of object and use map to traverse the items of array inside the object.
e.g :
let obj = {
topic: "accessing array in an object",
fruits: [
{ name: "banana", price: 30 },
{ name: "apple", price: 50 }
]
};
obj.fruits.map(fruit => console.log(fruit.name));
I hope, it helps you.
Related
I have an object in an array called "Person".
Within the object "Person", there is an array called "info".
My goal is to get all the values with the prefix "age:" in an array "info" when filtering by "gender:male". So, my desired output will be 1 to 9 because I want also to remove duplicates.
Below is my code but the results are only two values (1 and 4). Maybe the output is one value per person.
I spent a lot of hours playing the code but no luck. That's why I bring my problem here hoping anybody who is an expert on this can help me.
<script>
var array = [
{
"person": {
"info": [
"age:1",
"age:2",
"age:3",
"age:4",
"age:5",
"age:6",
"gender:male"
]
},
"person": {
"info": [
"age:4",
"age:5",
"age:6",
"age:7",
"age:8",
"age:9",
"gender:male"
]
},
"person": {
"info": [
"age:8",
"age:9",
"age:10",
"age:11",
"age:12",
"age:13",
"gender:female"
]
}
}
]
var filteredAges = [];
for (i = 0; i < array.length; i++) {
var infoGroup = array[i].person.info,
ageGroup = [];
for (j = 0; j < infoGroup.length; j++) {
ageGroup.push(infoGroup[j]);
var ageInfo = ageGroup.find(ages => ages.includes('age:'));
};
if (ageInfo) {
if (filteredAges.indexOf(ageInfo) == -1) {
filteredAges.push(ageInfo)
}
}
}
for (i = 0;i < filteredAges.length; i++) {
console.log(filteredAges[i]);
}
</script>
Seems like all your object keys are just person i.e
[
{
person: {...},
person: {...},
person: {...}
}
]
So when the variable array is evaluated it just has one person
You need to restructure your data maybe like below or something similar
Example - 1
[
{ person: {...} },
{ person: {...} },
{ person: {...} },
]
Example - 2
[
[ { person: {...} } ],
[ { person: {...} } ],
[ { person: {...} } ]
]
After fixing this you can try debugging your problem
If you want to get all items in info array that has "age:"
you can use filter like this
const ageInfos = [
"age:8", "age:9",
"age:10", "age:11",
"age:12", "age:13",
"gender:female"
].filter(x => x.startsWith("age:"))
Your output - ageInfos will be
["age:8", "age:9", "age:10", "age:11", "age:12", "age:13"]
You can also use Set to only collect unique strings or just push everything to an array and later use Set to return only unique values like this
const arrayWithDuplicates = ['a', 1, 'a', 2, '1'];
const unique = [...new Set(arrayWithDuplicates)];
console.log(unique); // unique is ['a', 1, 2, '1']
First of all, your JSON is wrong. You just overright person object.
Data structure is really awful, I would recommend you to rethink it.
Assuming person will not be overwritten I came up with this solution.
var array = [
{
"person": {
"info": [
"age:1",
"age:2",
"age:3",
"age:4",
"age:5",
"age:6",
"gender:male"
]
},
"person1": {
"info": [
"age:4",
"age:5",
"age:6",
"age:7",
"age:8",
"age:9",
"gender:male"
]
},
"person2": {
"info": [
"age:8",
"age:9",
"age:10",
"age:11",
"age:12",
"age:13",
"gender:female"
]
}
}
]
let agesArray = []
let ages = []
array.forEach((peopleObj) => {
for (const index in peopleObj) {
ages = peopleObj[index].info.map((age) => {
const ageNumber = age.split(':')[1]
if (parseInt(ageNumber)) {
return ageNumber
}
}).filter(val => !!val)
agesArray = [...agesArray, ...ages]
}
})
Thanks a lot guys. I'll apply all of your ideas and try if it can solve my problem.
I've got an array of three people. I want to add a new key to multiple objects at once based on an array of indices. Clearly my attempt at using multiple indices doesn't work but I can't seem to find the correct approach.
var array = [
{
"name": "Tom",
},
{
"name": "Dick",
},
{
"name": "Harry",
}
];
array[0,1].title = "Manager";
array[2].title = "Staff";
console.log(array);
Which returns this:
[
{
"name": "Tom",
},
{
"name": "Dick",
"title": "Manager"
},
{
"name": "Harry",
"title": "Staff"
}
]
But I'd like it to return this.
[
{
"name": "Tom",
"title": "Manager"
},
{
"name": "Dick",
"title": "Manager"
},
{
"name": "Harry",
"title": "Staff"
}
]
You cannot use multiple keys by using any separator in arrays.
Wrong: array[x, y]
Correct: array[x] and array[y]
In your case, it will be array[0].title = array[1].title = "manager";
1st method::
array[0].title = "Manager";
array[1].title = "Manager";
array[2].title = "Staff";
array[0,1] will not work.
2nd method::
for(var i=0;i<array.length;i++) {
var msg = "Manager";
if(i===2) {
msg = "Staff"
}
array[i].title = msg
}
You can use a helper function like this
function setMultiple(array, key, indexes, value)
{
for(i in array.length)
{
if(indexes.indexOf(i)>=0){
array[i][key] = value;
}
}
}
And then
setMultiple(array, "title", [0,1], "Manager");
Try this: `
for (var i=0; var<= array.length; i++){
array[i].title = "manager";
}`
Or you can change it around so var is less than or equal to any n range of keys in the index.
EDIT: instead make var <= 1. The point is to make for loops for the range of indices you want to change the title to.
Assuming that you have a bigger set of array objects.
var array = [
{
"name": "Tom",
},
{
"name": "Dick",
},
{
"name": "Harry",
},
.
.
.
];
Create an object for the new keys you want to add like so:
let newKeys = {
'Manager': [0,2],
'Staff': [1]
}
Now you can add more such titles here with the required indexes.
with that, you can do something like:
function addCustomProperty(array, newKeys, newProp) {
for (let key in newKeys) {
array.forEach((el, index) => {
if (key.indexOf(index) > -1) { // if the array corresponding to
el[newProp] = key // the key has the current array object
} // index, then add the key to the
}) // object.
}
return array
}
let someVar = addCustomProperty(array, newKeys, 'title')
Hi I am trying push a javascript object inside an array in javascript using a for loop to iterate through the data. Here is how my code looks like.
var data = {"up": [{
"name": "jack",
"age" : 10
},
{
"name" : "jhon",
"age" : 12
}]};
var output = {};
var output_data = {
element: []
};
for (var key in data.up) {
output.user_name = data.up[key].name;
output_data.element.push(output);
}
console.log(output_data.element);
However as you can see in the example http://jsbin.com/fanazaxoda/edit?html,js,console only the second element is name 'jhon' is inserted in both occations. What am I doing wrong here? Please explain.
Move the output initialization inside for loop otherwise it push reference of object each time. Updating it's property may reflect in all array elements since all elements are referring the same object.
var output_data = {
element: []
};
for (var key in data.up) {
var output = {}; // create new empty object on each iteration
output.user_name = data.up[key].name;
output_data.element.push(output);
}
var data = {
"up": [{
"name": "jack",
"age": 10
}, {
"name": "jhon",
"age": 12
}]
};
var output_data = {
element: []
};
for (var key in data.up) {
var output = {};
output.user_name = data.up[key].name;
output_data.element.push(output);
}
console.log(output_data.element);
I have data that's in this format:
{
"columns": [
{
"values": [
{
"data": [
"Project Name",
"Owner",
"Creation Date",
"Completed Tasks"
]
}
]
}
],
"rows": [
{
"values": [
{
"data": [
"My Project 1",
"Franklin",
"7/1/2015",
"387"
]
}
]
},
{
"values": [
{
"data": [
"My Project 2",
"Beth",
"7/12/2015",
"402"
]
}
]
}
]
}
Is there some super short/easy way I can format it like so:
{
"projects": [
{
"projectName": "My Project 1",
"owner": "Franklin",
"creationDate": "7/1/2015",
"completedTasks": "387"
},
{
"projectName": "My Project 2",
"owner": "Beth",
"creationDate": "7/12/2015",
"completedTasks": "402"
}
]
}
I've already got the column name translation code:
r = s.replace(/\%/g, 'Perc')
.replace(/^[0-9A-Z]/g, function (x) {
return x.toLowerCase();
}).replace(/[\(\)\s]/g, '');
Before I dive into this with a bunch of forEach loops, I was wondering if there was a super quick way to transform this. I'm open to using libraries such as Underscore.
function translate(str) {
return str.replace(/\%/g, 'Perc')
.replace(/^[0-9A-Z]/g, function (x) {
return x.toLowerCase();
})
.replace(/[\(\)\s]/g, '');
}
function newFormat(obj) {
// grab the column names
var colNames = obj.columns[0].values[0].data;
// create a new temporary array
var out = [];
var rows = obj.rows;
// loop over the rows
rows.forEach(function (row) {
var record = row.values[0].data;
// create a new object, loop over the existing array elements
// and add them to the object using the column names as keys
var newRec = {};
for (var i = 0, l = record.length; i < l; i++) {
newRec[translate(colNames[i])] = record[i];
}
// push the new object to the array
out.push(newRec);
});
// return the final object
return { projects: out };
}
DEMO
There is no easy way, and this is really not that complex of an operation, even using for loops. I don't know why you would want to use regex to do this.
I would start with reading out the column values into a numerically indexed array.
So something like:
var sourceData = JSON.parse(yourJSONstring);
var columns = sourceData.columns[0].values[0].data;
Now you have a convenient way to start building your desired object. You can use the columns array created above to provide property key labels in your final object.
var sourceRows = sourceData.rows;
var finalData = {
"projects": []
};
// iterate through rows and write to object
for (i = 0; i < sourceRows.length; i++) {
var sourceRow = sourceRows[i].values.data;
// load data from row in finalData object
for (j = 0; j < sourceRow.length; j++) {
finalData.projects[i][columns[j]] = sourceRow[j];
}
}
That should do the trick for you.
Sorry I'm kind of new to JS; I have an array of object; how can I get the name of the object which has the key "user_key3" and obviously without having a loop and have a condition.
arr = [{
"name": "user1",
"key": "user_key1"
},{
"name": "user3",
"key": "user_key3"
},{
"name": "user2",
"key": "user_key2"
}]
Please let me know if you need more clarification
Thanks
You can do it the functional way, like this
var name;
arr.forEach(function(currentObject) {
if (currentObject.key === "user_key3") {
name = currentObject.name;
}
});
If you want to short-circuit on the first match, you can use Array.prototype.some, like this
var name;
arr.some(function(currentObject) {
if (currentObject.key === "user_key3") {
name = currentObject.name;
return true;
}
return false;
});
The OP had mentioned obviously without having a loop and have a condition. I would do it as below:
arr = [{
"name": "user1",
"key": "user_key1"
},{
"name": "user3",
"key": "user_key3"
},{
"name": "user2",
"key": "user_key2"
}];
var keyValMap = arr.map(function(n) { return n.key } );
var arrIndex = keyValMap.indexOf('user_key3');
alert(arr[arrIndex].name);
Fiddle
You'll have to iterate and check for the key
var user_name;
for (var i=0; i<arr.length; i++) {
if ( arr[i].key === 'user_key3' ) {
user_name = arr[i].name;
break;
}
}
FIDDLE
You've edited the question to include
obviously without having a loop and have a condition
but a loop and a condition is by far the most efficient and cross-browser way to do this, so why would you "obviously" not want this ?
An inefficient yet concise solution would be
var keyarr = arr.map(function(x) { return x.key } );
//keyarr is list of keys
var index=keyarr.indexOf("user_key3");
//arr[index] is your answer. Index will be -1 if the key doesn't exist
In general, finding an item that satisfies some arbitrary property in an array requires you to loop over the array:
function find(arr, name) {
for (var i=0; i<arr.length; i++) {
if ( arr[i].key === name ) {
return arr[i];
}
}
}
Then to find it,
var obj = find(arr, 'user_key3');
Using more functional solutions to find the item is fine too, but you still end up looping in some way.
However, if you are doing lookups by key, then an array of key-value pairs is not the best data structure. I would suggest using an object directly:
var map = {
'user_key1': 'user1',
'user_key2': 'user2',
'user_key3': 'user3'
}
Then lookup is simply:
map['user_key3'];
Try this - underscore.js
For Your Example -
_.where(arr, {key: "user_key3"});
You cannot do such thing with Objects in Javascript. Though here you have a combination of callbacks and loop:
arr = [{
"name": "user1",
"key": "user_key1"
},{
"name": "user3",
"key": "user_key3"
},{
"name": "user2",
"key": "user_key2"
}];
arr.forEach(function(elme){
for(var g in elme)
{
if(elme[g] == 'user_key3')
{
console.log("Found the value: "+g+" : "+elme[g]);
};
}
});