Using Google's Maps API, I want to be able to find the value of a key within an object by the value within an array within the same object. When I "Inspect Element" on my page in order to view the console, here is what it shows in terms of object structure:
results: {
address_components [
0: Object: {
long_name: "704",
short_name: "704",
types [
0:"street_number"
]
}
1: Object {...}
2: Object {...}
3: Object {...}
]
place_id:"8AS8D8F8A881C81DA6S6D8"
}
I want to be able to find "street_number" in the object so I can find the corresponding value of "704" that also resides in the object.
The tricky part is that the values within "address_compenents" are not always in the same order so I cannot just write results[0].address_components[0].long_name in my javascript to find it. I am restricted to javascript in this project so any answers in that language would be much appreciated. Thank you in advance!
Note: I am not opposed to using libraries like lodash or underscore if it helps solve the problem.
First find() the item, then read the required attribute.
Note that you should also think about and handle the case where there is no street_number in the response, which is not covered by this snippet.
var results = {
address_components: [{
long_name: "704",
short_name: "704",
types: [
"street_number"
]
}, {
long_name: "100",
short_name: "100",
types: [
"attribute_a"
]
}, {
long_name: "200",
short_name: "200",
types: [
"attribute_b"
]
}, {
long_name: "300",
short_name: "300",
types: [
"attribute_c"
]
}],
place_id: "8AS8D8F8A881C81DA6S6D8"
}
var streetNumber = results.address_components.find(function(item) {
return item.types.some(function(subitem) {
return subitem === 'street_number'
});
}).long_name;
console.log(streetNumber); // 704
it is possible to do it by using Array.filter()
results: {
address_components [
0: Object: {
long_name: "704",
short_name: "704",
types [
0:"street_number"
]
}
1: Object {...}
2: Object {...}
3: Object {...}
]
place_id:"8AS8D8F8A881C81DA6S6D8"
}
const result = results.address_components.find(item => item.types.indexOf('street_number') > -1)
const longName = result.long_name // 704
const shortName = result.short_name // 704
Related
I want to dynamically build this object with the data below.
var object1 = {
machines: [
{
node: "01",
ram: "8",
disks: [ {sdasize: '20'}, {sdbsize: '200'} ],
mounts: [ {mount: "/var/lib", size: "10"} , {mount: "/home", size: "140"}]
},
{
node: "02",
ram: "8",
disks: [ {sdasize: '75'}, {sdbsize: '300'} ],
mounts: [ {mount: "/var/log", size: "20"} , {mount: "/var/www/html", size: "200"}]
}
]
};
I want to be able to add new machines and make changes to any value or add more mounts to the array that is nested. I have been looking at this for some time with no solution as of yet.
You can do this:
var object1 = {machines: []}
function addMachines(node,ram,disks,mounts){
object1.machines.push({node:node,ram:ram,disks:disks,mounts:mounts})
}
Since machines is a array we can use push() to insert objects inside that array.
Now you can use addMachines function in a loop or based on eventlisteners, and build the object1 via parameters in that function
Edit:
As commented below you can also add a function to build your other objects, like disks and mount.
buildDisk(sdasize,sdbsize)
{
return [{sdasize:sdasize},{sdbsize:sdbsize}]
}
Usage:
addMachines('01','8',buildDisk(20,50),'nice')
what object1 would look like
machines:[
{
node:'01',
ram:'8',
disks:[
{
sdasize:20,
sdbsize:50
},
mounts:'nice'
}];
I want to fetch all the names and label from JSON without loop. Is there a way to fetch with any filter method?
"sections": [
{
"id": "62ee1779",
"name": "Drinks",
"items": [
{
"id": "1902b625",
"name": "Cold Brew",
"optionSets": [
{
"id": "45f2a845-c83b-49c2-90ae-a227dfb7c513",
"label": "Choose a size",
},
{
"id": "af171c34-4ca8-4374-82bf-a418396e375c",
"label": "Additional Toppings",
},
],
},
]
}
When you say "without loops" I take it as without For Loops. because any kind of traversal of arrays, let alone nested traversal, involve iterating.
You can use the reduce method to have it done for you internally and give you the format you need.
Try this :
const data = {
sections: [
{
id: "62ee1779",
name: "Drinks",
items: [
{
id: "1902b625",
name: "Cold Brew",
optionSets: [
{
id: "45f2a845-c83b-49c2-90ae-a227dfb7c513",
label: "Choose a size"
},
{
id: "af171c34-4ca8-4374-82bf-a418396e375c",
label: "Additional Toppings"
}
]
}
]
}
]
};
x = data.sections.reduce((acc, ele) => {
acc.push(ele.name);
otherName = ele.items.reduce((acc2, elem2) => {
acc2.push(elem2.name);
label = elem2.optionSets.reduce((acc3, elem3) => {
acc3.push(elem3.label);
return acc3;
}, []);
return acc2.concat(label);
}, []);
return acc.concat(otherName);
}, []);
console.log(x);
Go ahead and press run snippet to see if this matches your desired output.
For More on info reduce method
In the context of cJSON
yes, we can fetch the key value for any of the object.
1 - each key value is pointed by one of the objects. will simply fetch that object and from there will get the key value.
In the above case for
pre-requisition: root must contain the json format and root must be the cJSON pointer. if not we can define it and use cJSON_Parse() to parse the json.
1st name object is "sections" will use
cJSON *test = cJSON_GetObjectItem(root, "sections");
char *name1 = cJSON_GetObjectItem(test, "name" )->valuestring;
2nd name key value
cJSON *test2 = cJSON_GetObjectItem(test, "items");
char *name2 = cJSON_GetObjectItem(tes2, "name")->valuestring;
likewise, we can do for others as well to fetch the key value.
I am trying to use underscoreJs to manipulate a JavaScript object and having problems doing so.
Here is my example
var data = {
"label": "SomeName",
"parent": [{
"id": "parentId",
"resources": [{
"name": "ID1NAME",
"calls": [
"user_get", "user2_post", "user3_delete"
]
}, {
"name": "ID2",
"calls": [
"employee1_get", "employee2_delete", "employee3_update"
]
}]
}]
};
var res = _(data).chain().
pluck('parent').
flatten().
findWhere(function(item){
item === "user_get"
}).
value();
console.log(res);
Using an element which is a part of data.parent.calls[] (example : "user_get") I would like to extract its parent object, i.e. data.parent[0].
I tried above but always get undefined. I appreciate any help on this.
One of the problems you're having is your use of _.pluck. If you execute _.pluck over an object, it'll go over the keys of the object trying to retrieve the property you specified as the second argument (in this case, 'parent'). 'label' is a string and 'parent' is an array so thus the array that you get as a result is [undefined, undefined]. The rest will then go wrong.
One solution could be as follows:
function findCallIndexInParent(call, parent) {
return _.chain(parent)
.pluck('resources')
.flatten()
.findIndex(function (obj) {
return _.contains(obj.calls, call);
})
.value();
}
function findCall(call, data) {
var parent = data.parent;
return parent[findCallIndexInParent(call, parent)];
}
console.log(findCall('user_get', data));
findCall is just a convenient method that will pass the parent property of data to findCallIndexInParent (that will retrieve the index where call is) and return the desired object with the parent array.
Lodash (a fork of underscore) provides a method to get the property of an object that would have come really handy in here (sadly, underscore doesn't have it).
The explanation of findCallIndexInParent is as follows:
Chain the parent list
pluck the resources array
As pluck maps, it returns a list of lists so a flatten is needed.
Find the index of the element which calls contains call
Return the value (the index) of the object that contains call within parent.
Here's the fiddle. Hope it helps.
This would seem to do the trick.
function findByCall(data, call) {
return _.find(data.parent, function(parent) { //From data.parent list, find an item that
return _.some(parent.resources, function(resource) {//has such parent.resource that it
return _.includes(resource.calls, call); //includes the searched resource.calls item
});
});
}
//Test
var data = {
"label": "SomeName",
"parent": [{
"id": "parentId",
"resources": [{
"name": "ID1NAME",
"calls": [
"user_get", "user2_post", "user3_delete"
]
}, {
"name": "ID2",
"calls": [
"employee1_get", "employee2_delete", "employee3_update"
]
}]
}]
};
console.log(findByCall(data, 'user_get'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore.js"></script>
If I understand correctly, you want to get the index of the element in the parent array which has any resource with the specified call.
data = {
"label": "SomeName",
"parent": [{
"id": "parentId",
"resources": [{
"name": "ID1NAME",
"calls": [
"user_get", "user2_post", "user3_delete"
]
}, {
"name": "ID2",
"calls": [
"employee1_get", "employee2_delete", "employee3_update"
]
}]
}]
}
// find the index of a parent
const index = _.findIndex(data.parent, parent =>
// that has any (some) resources
_.some(parent.resources, resource =>
// that contains 'user_get' call in its calls list
_.contains(resource.calls, 'user_get')
)
)
console.log(index) // 0
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
If you want to find the actual parent object, use find instead of findIndex
If you want to find all parent objects matching this call, use filter instead of findIndex
I am looking to rename a variable with a different name depending on its level within a nested JSON dataset.
An example JSON file is the following:
[
{
key: "John Doe School",
values: [
{
key: "Mr. Brown",
values: [
{
key: "Joe",
TestScore: 95
},
{
key: "Sarah",
TestScore: 99
}
]
}
]
}
]
In this example, I would like to change the first-level "key" to "School", the second-level "key" to "Teacher", and the third-level "key" to "Student".
The JSON dataset would look like this following the changes:
[
{
School: "John Doe School",
values: [
{
Teacher: "Mr. Brown",
values: [
{
Student: "Joe",
TestScore: 95
},
{
Student: "Sarah",
TestScore: 99
}
]
}
]
}
]
Well, given your example, you could just do this...
var json = [
{
key: "John Doe School",
values: [
{
key: "Mr. Brown",
values: [
{
key: "Joe",
TestScore: 95
},
{
key: "Sarah",
TestScore: 99
}
]
}
]
}
];
json[0].key = "School";
json[0].values[0].key = "Teacher";
json[0].values[0].values[0].key = "Student";
json[0].values[0].values[1].key = "Student";
UPDATE FOLLOWING COMMENT
json[0]['School'] = json[0].key; // Add new key:value
delete json[0].key; // Delete previous one
json[0].values[0]['Teacher'] = json[0].values[0].key; // Add new key:value
delete json[0].values[0].key; // Delete previous one
json[0].values[0].values[0]['Student'] = json[0].values[0].values[0].key; // Add new key:value
delete json[0].values[0].values[0].key; // Delete previous one
json[0].values[0].values[1]['Student'] = json[0].values[0].values[1].key; // Add new key:value
delete json[0].values[0].values[1].key; // Delete previous one
I assume you will be looping through a number of different JSON objects however, so you would of course also need to implement that but the above structure should point you in the right direction ;)
I'm creating an index file in JSON, which I'm using as a sort-of-database index for a javascript application I'm working on.
My index will look like this:
{
"_id": "acomplex_indices.json",
"indexAB": {
"title": {
"Shawshank Redemption": [
"0"
],
"Godfather": [
"1"
],
"Godfather 2": [
"2"
],
"Pulp Fiction": [
"3"
],
"The Good, The Bad and The Ugly": [
"4"
],
"12 Angry Men": [
"5"
],
"The Dark Knight": [
"6"
],
"Schindlers List": [
"7"
],
"Lord of the Rings - Return of the King": [
"8"
],
"Fight Club": [
"9"
],
"Star Wars Episode V": [
"10"
],
"Lord Of the Rings - Fellowship of the Ring": [
"11"
],
"One flew over the Cuckoo's Nest": [
"12"
],
"Inception": [
"13"
],
"Godfellas": [
"14"
]
},
"year": {
"1994": [
"0",
"3"
],
"1972": [
"1"
],
"1974": [
"2"
],
"1966": [
"4"
],
"1957": [
"5"
],
"2008": [
"6"
],
"1993": [
"7"
],
"2003": [
"8"
],
"1999": [
"9"
],
"1980": [
"10"
],
"2001": [
"11"
],
"1975": [
"12"
],
"2010": [
"13"
],
"1990": [
"14"
]
}
}
}
So for every keyword (like Pulp Fiction), I'm storing the matching document-id(s).
My problem is with integers/numbers/non-string data, like the release year in the above example. This is stored as a string, while I had hoped it would be stored as a number.
I'm creating the index entries like this:
// indices = the current index file
// doc = the document to update the index with
// priv.indices = all indices defined for this application instance
// priv.indices.fields = index fields e.g. "year", "director", "title"
// priv.indices.name = name of this index
priv.updateIndices = function (indices, doc) {
var i, j, index, value, label, key, l = priv.indices.length;
// loop all indices to add document
for (i = 0; i < l; i += 1) {
index = {};
index.reference = priv.indices[i];
index.reference_size = index.reference.fields.length;
index.current = indices[index.reference.name];
for (j = 0; j < index.reference_size; j += 1) {
label = index.reference.fields[j]; // like "year"
value = doc[label]; // like 1985
// if document has a label field (e.g. doc.year = 1985)
if (value !== undefined) {
// check if the index file already contains an entry for 1985
index.current_size = priv.getObjectSize(index.current[label]);
if (index.current_size > 0) {
// check if the document id is already in the index
// in case the data is updated (e.g. change 1982 to 1985)
key = priv.searchIndexByValue(
index.current[label],
doc._id,
"key"
);
if (!!key) {
delete index.current[label][key];
}
}
// create a new array if 1985 is not in the index yet
if (index.current[label][value] === undefined) {
index.current[label][value] = [];
}
// add the document id to an existing entry
index.current[label][value].push(doc._id);
}
}
}
return indices;
};
This works fine, except that fields I want to store as non-strings (integers, numbers or datetime), like the year in the above example end up as strings in my index.
Question:
Is it at all possible to store "non-string" types in a JSON document? If so, can I also store the key of a key/value pair as a "non-string" element.
If not, would I have to add a parameter to my index definitions declaring the type of each key in order to modify the key-string when I run into it or is there a better way to do it?
Thanks!
Is it at all possible to store "non-string" types in a JSON document?
Yes. The value of a property can be a string, number, boolean, object, array or null (undefined is a notable exception - it's a native JavaScript type but it's not a valid JSON value).
Can I also store the key of a key/value pair as a "non-string" element?
No. The key name must always be a string. However, that doesn't mean you can't parse that string into some other JavaScript type. For example, if you have a string but need a number, you can use the parseInt function, or the unary + operator.
See the JSON grammar for more detail.
no you can't, in JSON keys are strings.
the best you can do is storing string representations of those keys, wether integer or objects(more complicated, you have to build a serialization function).
If you want to use only consecutive integers keys starting from 0, then you can use arrays.
According to the json spec, you can have a number anywhere you could have a value. So the key of an object must be a string, but the value can be a number. Also any of the values in an array can be a number.
The spec is beside the point though; I believe the issue is this line:
index.current[label][value].push(doc._id);
When you read doc._id, that is a string. If you want to store it in the JSON as a number, you need to cast it:
index.current[label][value].push(parseInt(doc._id, 10));
Also note that having just numbers as IDs is not valid HTML.