Traverse nested maps / objects from keys in an array - javascript

I think a code sample is going to work a lot better than my vocabulary:
var keys = ['folder','name'];
var data = { folder: { name: 'Special Folder' } };
Given the two vars above, I'm looking for a way to dynamically use the array as a way to look up the object keys (sort of like a "path"). So I need to programmatically produce the following:
data['folder']['name'] // that would give me 'Special Folder'
Hopefully this makes sense, I just can't quite put all the pieces together.
TIA

var keys = ['folder','name'];
var data = { folder: { name: 'Special Folder' } };
for(var i=0;i<keys.length;i++){
data = data[keys[i]];
}
alert(data)

Related

Swap elements in a multidimensional array in typescript

I have a multidimensional array which contains coordinates extracted from a back-end call, this is a screenshot of the structure:
I would like to swap those coordinates but I cannot know how to handle that. Thanks.
Many ways to accomplish what you're looking for. One approach is to loop through the structure until you reach the arrays you want to manipulate. In the snippet, I decided to make a function that took the original data and returns a new object. To 'swap' the contents of the arrays, I did a .splice(0) to make a copy of the array, then called .reverse() on it to switch the order.
The main challenge is working through the data structure - some fairly intuitive levels to the current structure you have (a coordinates object that contains a node called coordinates that is array - just a little confusing)
var dataFromTheServer = {
content: [
{
coordinates: {
coordinates: [
[17.25756,31.19192],
[15.1821, 40.87555],
[33.78433, 18.59314],
[17.25756,31.19192]
]
}
}
]
}
function swapEm(data){
var response = {};
if(data && data.content){
response.content = [{coordinates:{coordinates:[]}}];
for(var item in data.content){
if(data.content[item] && data.content[item].coordinates && data.content[item].coordinates.coordinates){
for(var coord in data.content[item].coordinates.coordinates){
response.content[0].coordinates.coordinates[coord] = data.content[item].coordinates.coordinates[coord].splice(0).reverse()
}
}
}
}
return response;
}
console.log(dataFromTheServer);
console.log(swapEm(dataFromTheServer))

Problem with a JSON Object ( deep search )

Hi Guys i have a big Problem, i've been trying to solve it for days.I have an entangled JSON Object ( http://ddragon.leagueoflegends.com/cdn/9.1.1/data/de_DE/runesReforged.json ) and for example this Array with my ID's in it.
0: 8214 1: 8112 2: 8005 3: 8010 4: 8112 5: 8359 6: 8437 7: 9923 8: 8112 9: 8021
And I want the id to be searched for with the help of this array in the json Object. And after a match, the content of "icon" should be returned,
but i dont know how :(
I tried it on so many ways, but i dont have the result that i want. The ID's are among others under the_json_object[0].slots[0].runes[0].id
I read that you could solve it with recursive functions but I tried and did not get the desired result.
Maybe you guys can help me :) i would be very thankful
If I've understood you correctly you could do something roughly as follows:
var ids = [8214,8112,8005,8010,8112,8359,8437,9923,8112,8021];
var results = [];
ids.map(function(id) {
results.push({key: id, icon: ''});
});
Then given your object you could map through it's children as folllows:
the_json_object.map(function(item){
item.slots.map(function(slot){
slot.runes.map(function(rune){
if(ids.indexOf(rune.id) != -1) {
results.map(function(result){
if(result.key == rune.id) result.icon = rune.icon;
});
}
});
});
});
var icons = [];
results.map(function(result){
icons.push(result.icon);
});
logging the icons object would then provide you a string array of icons as follows:
["perk-images/Styles/Domination/Electrocute/Electrocute.png", "perk-images/Styles/Domination/HailOfBlades/HailOfBlades.png", "perk-images/Styles/Inspiration/Kleptomancy/Kleptomancy.png", "perk-images/Styles/Precision/PressTheAttack/PressTheAttack.png", "perk-images/Styles/Precision/FleetFootwork/FleetFootwork.png", "perk-images/Styles/Precision/Conqueror/Conqueror.png", "perk-images/Styles/Resolve/GraspOfTheUndying/GraspOfTheUndying.png", "perk-images/Styles/Sorcery/SummonAery/SummonAery.png"]
Hope this helps.
Matt
I think the suitable way would be to sort data. You can do this by splitting the string.
If you split the string on the basis of White spaces you can get key value pairs.
For example from string *
0:8214 1:8112 2:8005 3:8010 4:8112 5:8359 6:8437 7:9923 8:8112 9:8021
var res = str.split(" ");
if you split with white space it will provide you with key value pairs from which you can form a list of objects and it will be easy for you search from it.
If you want an flat array with the all the needed icons, you could use something like this:
let the_runes = [ 8214, 8112, 8005 /* ... */ ];
let the_icons = [];
for (let first_level_obj of the_json_object) {
for (let slot_obj of first_level_obj.slots) {
for (let rune_obj of slot_obj.runes) {
if (the_runes.includes(rune_obj.id)) {
the_icons.push({
id: rune_obj.id,
icon: rune_obj.icon
});
}
}
}
}
The the_icons-array will hold objects with id and its corresponding icon as its properties.

Add [DataObject] to exsisting array with var key

Using Cordova, I am trying to get an Object to add to an array. I have this working on node JS using :
theData = {[varkey]:DataObject};
But I can't get this to work the same way within my javascript that cordova runs.
I need to do the following:
var TownName = 'Auckland', var townData = (JSON Data);
theArray = new Array();
theArray[TownName] = townData;
I need to be able to call it back as:
theArray['Auckland']
Which will return (JSON Data)
But it doesn't want to store the data with the key inside the array.
I have also tried:
theArray.TownName = townData;
theArray = [{TownName:townData}];
theArray = {[TownName]:townData}];
Nothing wants to store the data.
Any suggestions?
::EDIT::
data.theData =
"Auckland"[
{
"username":"pndemoname1",
"number":"373456",
"www":"http://373456.pndemoname1",
"icon":"/imgs/pndemoname1.png"
},
{
"username":"pndemoname2",
"number":"373458",
"www":"http://373458.pndemoname2",
"icon":"/imgs/pndemoname2.png"
}
data.town = "Auckland";
townData = new Array();
alert(JSON.stringify(data.theData))//Alerts theData
townData[data.town] = data.theData
alert(townData[townName]) //Alerts undefined
::EDIT2::
Re-defining the array within the function that deals with all of the data, seems to make it work.
As per my answer, the issue was that I assumed javascript vars are global.
Use objects or an array of objects.
A data structure like this:
{
town1: town1Data,
town2: town2Data,
}
Or more common:
[
{
name: "Town 1",
data: {...}
},
{
name: "Town 2",
data: {...}
},
]
For reference:
http://andrewdupont.net/2006/05/18/javascript-associative-arrays-considered-harmful/
I got what you're trying to do, to add property names dynamically to your object is first, by making sure you are using an OBJECT instead of an array, so when you want to store something you will do the following:
var _obj = {}, _something = 'xyz';
_obj[ _something ] = { ... }; // json structure
The problem you're facing is that you want to assign a string value as a key inside your array, which will not work.
However, you can still use the array you defined and do the following:
var _array = new array();
_array.push( { .... } ); // insert json structure
Remember! By using the array you will have to loop through all values every time you want to access your key, just as the best practice to avoid getting into errors.
Good luck.
The issue was that I didn't define the array within the function of where I was trying to add the information to.
I assumed the var was global (Too much PHP)

Turn Observable Array into nested JSON

I'm having a problem getting an array of information stored properly as JSON.
I made a fiddle to illustrate the problem. Enter a set of tags and take a look at the console to see the output.
More explanation:
So I have an input that takes in a comma-separated list of tags, which I then format.
function createTagArray() {
// given an input value of 'tag1, tag2, tag3'
// returns array = ['tag1', 'tag2', 'tag3']
}
I thought what I needed to do next was the following:
loop over the array and create a 'tag' object for each item which also includes an id for the tag and the id of the contact the tag is associated with.
Each object is pushed to tags, an observable array.
function single_tag(id, contactId, tagLabel) {
var self = this;
self.id = id;
self.contactId = contactId;
self.tagLabel = tagLabel;
}
function createTags() {
var array = createTagArray();
for (var i = 0; i < array.length; i++) {
self.tags().push(new single_tag(uuid.generate(), self.contactId, array[i]));
}
}
Then, I converted it into JSON
self.contactInformation = function() {
return ko.toJS({
"id": self.contactId,
"firstname": self.firstname(),
"lastname": self.lastname(),
... other fields ...
"tags": self.tags(),
})
}
But, when I inspect the console output of calling this function, tags is a collection of arrays, not a nice json object.
How do I get it formatted correctly?
I tried this suggestion, and the tag json is structured correctly, but it is stored with escaped quotes, so that seems wrong.
Thanks for all the help!
I would recommend you knockout.mapping plugin for KO, it allow map complicated JSON structure to view model, even without declarations.
From the documentation
Let’s say you have a JavaScript object that looks like this:
var data = {
name: 'Scot',
children: [
{ id : 1, name : 'Alicw' }
]
}
You can map this to a view model without any problems:
var viewModel = ko.mapping.fromJS(data);
Now, let’s say the data is updated to be without any typos:
var data = {
name: 'Scott',
children: [
{ id : 1, name : 'Alice' }
]
}
Two things have happened here: name was changed from Scot to Scott and children[0].name was changed from Alicw to the typo-free Alice. You can update viewModel based on this new data:
ko.mapping.fromJS(data, viewModel);
And name would have changed as expected. However, in the children array, the child (Alicw) would have been completely removed and a new one (Alice) added. This is not completely what you would have expected. Instead, you would have expected that only the name property of the child was updated from Alicw to Alice, not that the entire child was replaced!
...
To solve this, you can specify which key the mapping plugin should use to determine if an object is new or old. You would set it up like this:
var mapping = {
'children': {
key: function(data) {
return ko.utils.unwrapObservable(data.id);
}
}
}
var viewModel = ko.mapping.fromJS(data, mapping);
In the jsfiddle you were using Knockout 3.0 which doesn't have support for textInput. This was added in 3.2. To use version 3.2 you need to use a cdn such as this: http://cdnjs.com/libraries/knockout
There was typeo in your binding. sumbit should be submit.
There was a problem with your constructor for single_tag. id was not used so I removed it:
function single_tag(contactId, tagLabel) {
var self = this;
self.contactId = contactId;
self.tagLabel = tagLabel;
}
Currently also contactId is not set because the observable has not been set to a value.
To convert to JSON you need to use ko.toJSON instead of ko.toJS:
self.contactInformation = function() {
return ko.toJSON({
"firstname": self.firstname(),
"tags": self.tags(),
})
}
Now when the console writes out an array appears:
{
"firstname":"test",
"tags":[
{"tagLabel":"test1"},
{"tagLabel":"test2"},
{"tagLabel":"test3"}
]
}
JsFiddle
So my problem was more basic than I was realizing. I'm using JSON Server to serve up my data, and I was pulling information from two parts of the database (contacts & tags).
When I tried to update my tags, I was trying to apply them to a property that didn't exist on the contact JSON in my database. Posting the tags separately worked though.

Accessing a javascript object in D3.js

A javascript data object (JSON notation) has been created with the following content:
"[
{"range":"Shape","values":[{"idx":0,"val":"Random"},{"idx":1,"val":"Line"},{"idx":2,"val":"Square"},{"idx":3,"val":"Circle"},{"idx":4,"val":"Oval"},{"idx":5,"val":"Egg"}]},
{"range":"Color","values":[{"idx":0,"val":"Red"},{"idx":1,"val":"Blue"},{"idx":2,"val":"Yellow"},{"idx":3,"val":"Green"},{"idx":4,"val":"Cyan"}]}
]"
In a next step the index of an ordinal value has to be found in this object. The function should find the index of the value 'Blue' in the range 'Color'.
So the function should have the meta scripting form
f("Color")("Blue")=1
What is the most elegant form to create such a function in the context of D3 and javascript?
Depending on your use case, it might make sense to convert the data structure to a different structure more suitable for direct access. E.g. you could convert your structure to
var data = {
Shape: ['Random', 'Line', ...],
// ...
};
and access it with
data['Shape'].indexOf('Line') // or data.Shape.indexOf('Line')
Or go even one step further and convert to
var data = {
Shape: {
Random: 0,
Line: 1,
// ...
},
// ...
};
and access it with
data['Shape']['Line'] // or data.Shape.Line
What the best solution is depends on the actual use case.
Converting the structure dynamically is pretty straight forward. Here is an example to convert it to the first suggestion:
var newData = {};
data.forEach(function(item) {
newData[item.range] =
item.values.map(function(value) { return value.val; });
});
This would also reduce redundancy (e.g. idx seems to correspond with the element index).
Would this work for you ?
var dataJson = '[ \
{"range":"Shape","values":[{"idx":0,"val":"Random"},{"idx":1,"val":"Line"},{"idx":2,"val":"Square"},{"idx":3,"val":"Circle"},{"idx":4,"val":"Oval"},{"idx":5,"val":"Egg"}]},\
{"range":"Color","values":[{"idx":0,"val":"Red"},{"idx":1,"val":"Blue"},{"idx":2,"val":"Yellow"},{"idx":3,"val":"Green"},{"idx":4,"val":"Cyan"}]}\
]';
var data = JSON.parse(dataJson);
for (each in data){
if ( (data[each].range) === 'Color'){
for (eachVal in data[each].values){
if (data[each].values[eachVal].val === 'Blue'){
alert(data[each].values[eachVal].idx);
}
}
} ;
}
And here is the JSFiddle for you too.

Categories

Resources