I have an Array with this kind of values:
val = [ ['L-2-4-1','john','bla1'],
['L-1-1-26','bohn','bla2'],
['L-2-1','cohn','bla3'],
['L-1-1-05','rohn','bla4'],
['L-1-1','gohn','bla5']
['L-2-3-1','zohn','bla-finally'] ];
The number-sequence is always unique and "0" is never used.
What I'm trying to get would be something like this:
ser = [ [undefined],
[ [undefined],[ ['gohn'],['bla5'] ], [undefined], ... , [ ['bohn'], ['blah2'] ] ],
...
];
The purpose is to be able to access the data like this:
ser[2][4][1][0]; // Array('john','bla1')
ser[1][1][0]; // Array('gohn','bla5')
ser[1][1][26][0]; // Array('bohn','bla2')
and also to loop through all elements.. for instance:
for(var i = 0; i <= ser[1][1].length; i++){ //code }
The main problem I have is that I was not able to set the variables the same way I intend to read them. Because this does NOT work, since I need to declare all arrays separately as arrays (right?)
var ser[1][1][26][0] = ['john','bla1']; // Nop;
I don't know the maximum depth of the tree
Trying to build the arrays from "inside out" or from "right to left" -however it is best described- I always end up overwriting previously set array elements.
Maybe the whole idea is too complicated (or at least not ideal) for the purpose? What would you suggest? I have the feeling I´m trying to do the right thing but the wrong way... Something like organizing marbles on a glass surface. Everything keeps moving around...
Have you considered representing your data in JSON?
It allows for complex structures that are otherwise too confusing to keep in your head. It's like XML meets JavaScript arrays. Rather self-describing and easy to follow. You can read the lengths and sizes of objects easily and it's quite fast. You can use values instead of array positions and re-think the structure of your data.
http://json.org/example.html
Here is a record in JSON:
{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters":
{
"batter":
[
{ "id": "1001", "type": "Regular" },
{ "id": "1002", "type": "Chocolate" },
{ "id": "1003", "type": "Blueberry" },
{ "id": "1004", "type": "Devil's Food" }
]
},
"topping":
[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5005", "type": "Sugar" },
{ "id": "5007", "type": "Powdered Sugar" },
{ "id": "5006", "type": "Chocolate with Sprinkles" },
{ "id": "5003", "type": "Chocolate" },
{ "id": "5004", "type": "Maple" }
]
},
http://labs.adobe.com/technologies/spry/samples/data_region/JSONDataSetSample.html
short and sweet:
var i, j, t, final = [];
for (i = 0; i < val.length; i++) {
t = val[i][0].split('-');
for (j = 1; j < 5; j++) {
t[j] = parseInt(t[j], 10) || 0;
}
final[t[1]] = final[t[1]] || [];
final[t[1]][t[2]] = final[t[1]][t[2]] || [];
final[t[1]][t[2]][t[3]] = final[t[1]][t[2]][t[3]] || [];
final[t[1]][t[2]][t[3]][t[4]] = final[t[1]][t[2]][t[3]][t[4]] || [];
final[t[1]][t[2]][t[3]][t[4]].push(val[i].slice(1));
}
final now has the correct data as you specified...
however, you might want to consider using objects instead of arrays (change all [] to {}) as the random insertion points in arrays lead to series of empty (null) values, the only caveat would be that you'd have to use a for (var key in obj) style loop...
hope this helps -ck
IF YOU NEED DYNAMIC DEPTH
var i, j, t, o, depth = 4, final = [];
for (i = 0; i < val.length; i++) {
t = val[i][0].split('-');
o = final;
for (j = 1; j <= depth; j++) {
t[j] = parseInt(t[j], 10) || 0;
o[t[j]] = o[t[j]] || [];
o = o[t[j]];
}
o.push(val[i].slice(1));
}
now depth is the constant at which the data is stored missing or unparsable "keys" or "indices" depending on how you want to think of them, default to 0
enjoy -ck
Related
I have hierarchical data being used to create an svg in my application. I need to find the length of the longest chain in that datasource. I could go through the datasource level by level, recursively going deeper into it to read _children, calling a recursive function to count the levels, but I am sure there must be a better way. This is further complicates because the datasource can go both directions from the node it starts on with _children and _parents.
var findChildren = function (ds, level) {
if (!ds._children || ds._children.length == 0) {
return level;
}
var longest = level + 1;
ds._children.forEach(function (item) {
var result = findChildren(item, level + 1);
if (result > longest) {
longest = result;
}
});
return longest;
}
This is the function I am currently using, with an identical one that checks ds._parents to go the other way, passing the result of one as the starting level of the other. I am just sure there must be a better way...
For example, the same data could be in three ways, depending where the user opened the tree from.
{"number":1,"type":"Delivery","_parents":[{"number":1,"type":"Order","_parents":[{"number":1,"type":"Quote"}]}]}
{"number":1,"type":"Order","_parents":[{"number":1,"type":"Quote"}],
"_children":[{"number":1,"type":"Delivery"}]}
{"number":1,"type":"Quote","_children":[{"number":1,"type":"Order","_children":[{"number":1,"type":"Delivery"}]}]}
You said that you...
need to find the length of the longest chain in that datasource.
That is the length going to the root to the deepest leaf in the data structure. There are convenient D3 methods to quickly find the deepest leaf.
So, suppose we have a hierarchical data like this:
{
"name": "Eve",
"children": [{
"name": "Cain"
}, {
"name": "Seth",
"children": [{
"name": "Enos"
}, {
"name": "Noam"
}]
}, {
"name": "Abel"
}, {
"name": "Awan",
"children": [{
"name": "Enoch"
}]
}, {
"name": "Azura"
}]
}
When you pass it to d3.hierarchy()...
var hierarchy = d3.hierarchy(data);
... it automatically creates a property named depth in each node:
node.depth - zero for the root node, and increasing by one for each descendant generation.
So, we just need a simple function to get the biggest depth value. For instance:
var longest = d3.max(hierarchy.descendants().map(function(d) {
return d.depth
}));
Here is a demo:
var data = {
"name": "Eve",
"children": [{
"name": "Cain"
}, {
"name": "Seth",
"children": [{
"name": "Enos"
}, {
"name": "Noam"
}]
}, {
"name": "Abel"
}, {
"name": "Awan",
"children": [{
"name": "Enoch"
}]
}, {
"name": "Azura"
}]
};
var hierarchy = d3.hierarchy(data);
var longest = d3.max(hierarchy.descendants().map(function(d) {
return d.depth
}));
console.log("The longest chain has " + (longest + 1) + " levels.")
<script src="https://d3js.org/d3.v4.min.js"></script>
I have two arrays
$scope.tags = [{ "id": 1, "name": "python" }, { "id": 2, "name": "NodeJs" }, { "id": 3, "name": "git" }]
Other one is
$scope.skillsInterested = [1,2];
What is want to do ?
How can i map the above arrays and print only names of the id's in$scope.skillsInterested
I want to print names in first array only the id's present in second.
I have tried this after getting several answers
var tag_map = {};
for (var x = 0; x < $scope.tags.length; x++) {
tag_map[$scope.tags[x]['id']] = $scope.tags[x]['name'];
}
$scope.skillsInts = $scope.skillsInterested.map(function(x) {
return tag_map[x]
On running console.log
console.log("Result", tag_map);
It sometimes give result sometimes it gives 'map' of undefined.
TypeError: Cannot read property 'map' of undefined
at controllers.js:141
at angular.js:16383
at m.$eval (angular.js:17682)
at m.$digest (angular.js:17495)
at m.$apply (angular.js:17790)
at l (angular.js:11831)
at J (angular.js:12033)
at XMLHttpRequest.t.onload (angular.js:11966)
Thanks in advance.
Make a map of your data that looks like this:
var tagMap = { 1: "python", 2: "NodeJs" /* etc. */ };
You can do this by looping over your tags and adding a new property to an object. reduce lets you do this without creating any extra variables.
Then, you can select names from your newly created object using the [] notation: tagMap[1] returns "pyhton".
var tags = [{ "id": 1, "name": "python" }, { "id": 2, "name": "NodeJs" }, { "id": 3, "name": "git" }]
var selectedExpTags = [1,2];
// Make a map for `id: name`
var tagMap = tags.reduce(function(map, tag) {
map[tag.id] = tag.name;
return map;
}, {});
// Quickly select names from the map:
var selectedNames = selectedExpTags.map(function(id) {
return tagMap[id];
});
console.log(selectedNames);
Using this approach, you minimise the iterations over your data. The creation of the map loops over the tags once. Creating the array with names, loops over the selected tags once. So, roughly, the "loop count" is tags.length + selectedTags.length. If you would use an indexOf based approach, your loop count would be tags.length * selectedTags.length.
Use the filter function for first, and then check the id's existnent then map the names from the array.
var first = [{ "id": 1, "name": "python" }, { "id": 2, "name": "NodeJs" }, { "id": 3, "name": "git" }];
var selectedExpTags = [1,2];
var names = first.filter(item => selectedExpTags.some(id => item.id === id)).map(item => item.name);
console.log(names);
You can loop over $scope.selectedExpTags and get a list of all names. You can use array.find if you want first value only.
Sample
var first = [
{ "id": 1, "name": "python" },
{ "id": 2, "name": "NodeJs" },
{ "id": 3, "name": "git" }];
var selectedExpTags = [1,2];
var names = selectedExpTags.map(x=> first.find( y=> y.id === x ).name )
console.log(names);
$scope.newArray = []; // If you need a new array to work with
angular.forEach($scope.tags, function(tag){
$scope.selectedExpTags.forEach(function(selectedTag){
if(selectedTag == tag.id){
//tag.hide = false; // - If you want to update the current array
$scope.newArray.push(tag);
}
// else{ // - If you want to update the current array
// tag.hide = true;
// }
})
})
Lodash is more efficient than angular for manipulating data.
This is the sample json:
{
"search": {
"facets": {
"author": [
],
"language": [
{
"value": "nep",
"count": 3
},
{
"value": "urd",
"count": 1
}
],
"source": [
{
"value": "West Bengal State Council of Vocational Education & Training",
"count": 175
}
],
"type": [
{
"value": "text",
"count": 175
}
],
}
}
There are several ways to delete key search.facets.source:
delete search.facets.source
delete jsobObj['search']['facets']['source']
var jsonKey = 'source';
JSON.parse(angular.toJson(jsonObj), function (key, value) {
if (key != jsonKey)
return value;
});
Above 1 & 2 are not dynamic, and 3 is one of the way but not a proper way. Because if source is present in another node then it will not work. Please anybody can tell me how to delete it dynamically in any kind of nested key. Because we can not generate sequence of array dynamically in above 2.
Assuming you're starting from this:
let path = 'search.facets.source';
Then the logic is simple: find the search.facets object, then delete obj['source'] on it.
Step one, divide the path into the initial path and trailing property name:
let keys = path.split('.');
let prop = keys.pop();
Find the facets object in your object:
let parent = keys.reduce((obj, key) => obj[key], jsonObj);
Delete the property:
delete parent[prop];
I have found out another solution, it is very easy.
var jsonKey = 'search.facets.source';
eval('delete jsonObj.' + jsonKey + ';');
Problem : Can not render second level in the JSON file for some reason but first level works. Second level is giving me undefined error. Please help.
HTML:
<div>
<li data-item="item1">1<p></p><span></span></li>
<li data-item="item2">2<p></p><span></span></li>
<li data-item="item3">3<p></p><span></span></li>
<li data-item="item4">4<p></p><span></span></li>
</div>
JS/JSON
var data = [
{
"word": "hello",
"favnumber": "0070",
"item": "item1",
"color": "red"
},
{
"word": "hello world",
"favnumber": "0233070",
"item": "item2",
"color": "blue",
"Promo": {
"Price": 3.99
}
},
{
"word": "hello mom",
"favnumber": "0070",
"item": "item3",
"color": "pink",
"Promo": {
"Price": 4.99
}
},
{
"word": "hello dad",
"favnumber": "0070",
"item": "item4",
"color": "silver",
"Promo": {
"Price": 8.99
}
}
];
var items = document.querySelectorAll('[data-item]');
for (var e in items) {
var element = items[e];
var name = $(element).attr('data-item');
for (var i in data) {
var item = data[i];
if (name == item.item) {
var colorValue = item.color
var promoPriceValue = item.Promo.Price //this doesn't work//
$(element).find('p').text(colorValue)//this works//
$(element).find('span').text(promoPriceValue)
}
}
}
Example: http://jsfiddle.net/icovermaface/24L02a1q/1/
In addition to not all your objects in data having the exact same data-structure, I would change your for loops from the for ... in pattern to an iterated variable since you are iterating over an array and not enumerating over a javascript object. In other words:
for(var e=0; e < items.length; e++)
and
for(var i=0; i < data.length; i++)
Here is some more info on why not to use the for ... in pattern with arrays: Why is using "for...in" with array iteration a bad idea?
The first item in your array doesnt have a Promo field. This is throwing the undefined error. Do a check to see if the field exists before trying to access it or create a default value
check
if(item.Promo) {
var promoPriceValue = item.Promo.Price
}
default
var promoPriceValue = item.Promo ? item.Promo.Price : 10.99
Also you should change your loop structure, to a for (var i = 0; i < data.length; i++) as Jason mentioned. As structured they throw this error:
Uncaught TypeError: Cannot use 'in' operator to search for 'getAttribute' in 4
working fiddle - https://jsfiddle.net/24L02a1q/7/
Is it possible using JavaScript only to replace all instances of the version with another number and then return the JSON structure intact?
{
"savedSearches": [{
"id": 123,
"version": 10,
"name": "Project Manager",
"query": "www.foo.com"
}, {
"id": 123,
"version": 10,
"name": "Project Manager",
"query": "www.foo.com"
}],
"deletedSavedSearches": []
}
I need this to be very quick and lightweight as I'll be using it within JMeter.
JSON structure is nothing more than a JavaScript object. You can iterate over its properties and modify their values as usual. For instance, to increase each version by one:
var json = { … }
for (var i in json.savedSearches) json.savedSearches[i].version += 1;
You can try this
var jsonObject = JSON.parse(yourJSONString);
for(var i = 0, len = jsonObject.savedSearches.length; i < len; i++) {
jsonObject.savedSearches[i].version = "Number you want here";
}
If you, for some reason, want to return a string:
JSON.stringify(jsonObject)
If you already have the object, you can skip the JSON.parse