I have an array that is created from an API call.
Here is how I make this array-
var data5 = ko.observableArray(); /*Most important thing to make the data array observable otherwise it will not show the data of the REST API*/
var arrow = [];
function practiceData() {
// var data = [];/**/
$.getJSON("REST API").then(function(dataset) {
$.each(dataset, function(index, value) {
//console.table((dataset));
//console.log(value.change);
data5.push(value); // PUSH THE VALUES INSIDE THE ARRAY.
arrow.push(value.change);
console.log("arrow", arrow);
arrow.forEach(function(value) {
if (value == 0) {
$("#triangle-down-small").hide();
$("#triangle-up-small").hide();
console.log("rgjak")
console.log(value);
// document.getElementById("navTabBar").style.visibility = "none";
} else if (value < 0) {
// $("#triangle-down-small").hide();
$("#triangle-up-small").hide();
console.log("hcdsb")
console.log(value);
}
});
});
});
}
console.log(arrow)-
arrow (1) [0]
arrow (2) [0, 0]
arrow (3) [0, 0, -100]
JSON Response Structure-
[
{
"change": 0,
"count": 6,
"duration": 4,
"prevcount": 6,
"subcategory": "Consultancy"
}
]
I am not able to iterate through the array as for the if-else condition the .hide() function works for just the if condition not for the else-if.
Any help is appreciated.
Thanks in advance.
Just for your reference, Move loop after $.each. But no point of coding like this.Bad practice
function practiceData() {
$.getJSON("REST API").then(function (dataset) {
$.each(dataset, function (index, value) {
data5.push(value); // PUSH THE VALUES INSIDE THE ARRAY.
arrow.push(value.change);
});
console.log("arrow", arrow);
arrow.forEach(function (value) {
if (value == 0) {
console.log("rgjak");
console.log(value);
} else if (value < 0) {
console.log("hcdsb");
console.log(value);
}
});
});
}
The array foreach function is very simple and basic, so there is nothing wrong with that.
I guess your problem is that your data structure not being consistent or you have a logic problem in your code.
You should make sure to always check that the values you push into the array exist and are numbers.
e.g
if (!value || typeof value.change === 'undefined') {
return ;
}
Also, given your json response data, [0, 0, -100]
both if and else statements will run and both buttons will be hidden.
As long as there is one zero in your array, both buttons will be hidden.
Related
I have the below JSON string. The id-dashes in the file are not optional unfortunately, neither is the syntax. I would like to extract the "dd" values with JavaScript/Node.
{
"a-id":{
"b-id":"random",
"bb-id":"random",
"bbb-id":"random",
"bbbb-id":{
"c":[
{
"d":"random",
"dd":"This_info_is_needed"
},
{
"d":"random",
"dd":"This_info_is_needed"
},
{
"d":"random",
"dd":"This_info_is_needed"
},
{
"d":"random",
"dd":"This_info_is_needed_2"
}
]
},
"bbbbb-id":"random",
"bbbbbb-id":"random"
}
}
I would be open to use any additional helper like lodash, jQuery, etc.
The output should be an array with: This_info_is_needed and This_info_is_needed_2.
Thank you in advance.
You can create custom function that will search your data deep and return value if key is dd using for...in loop.
var obj = {"a-id":{"b-id":"random","bb-id":"random","bbb-id":"random","bbbb-id":{"c":[{"d":"random","dd":"This_info_is_needed"},{"d":"random","dd":"This_info_is_needed"},{"d":"random","dd":"This_info_is_needed"},{"d":"random","dd":"This_info_is_needed"}]},"bbbbb-id":"random","bbbbbb-id":"random"}}
function getDD(data) {
var result = []
for(var i in data) {
if(i == 'dd') result.push(data[i])
if(typeof data[i] == 'object') result.push(...getDD(data[i]))
}
return result
}
console.log(getDD(obj))
If you just interested in the values only, can also just do this:
var obj = {"a-id":{"b-id":"random","bb-id":"random","bbb-id":"random","bbbb-id":{"c":[{"d":"random","dd":"This_info_is_needed"},{"d":"random","dd":"This_info_is_needed"},{"d":"random","dd":"This_info_is_needed"},{"d":"random","dd":"This_info_is_needed"}]},"bbbbb-id":"random","bbbbbb-id":"random"}};
var desiredResults = obj['a-id']['bbbb-id']['c'].map(function(data){return data.dd});
console.log(desiredResults);
I want to loop through this object and add the 'loc' value to an array if their side = 2. What am I doing wrong?
2025 is the the room object and the entire things is rooms.
//Object
{
"2025": {
"tom": {
"side": 1,
"loc": 111
},
"billy": {
"side": 2,
"loc": 222
},
"joe": {
"side": 2,
"loc": 333
},
"bob": {
"side": 1,
"loc": 444
}
}
}
//Code
var side2 = [];
for (var key in rooms[room]) {
if (rooms[room].hasOwnProperty(key)) {
var obj = rooms[room][key];
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
if(prop == 'loc') {
if(obj[prop] == 2) {
side2.push(key);
}
}
}
}
}
}
console.log(side2);
You want to push when the side value is 2, so you want to check side and not loc. Then you can simply push obj.loc
...
if (obj.hasOwnProperty(prop)) {
if(prop == 'side') {
if(obj[prop] == 2) {
side2.push(obj.loc);
}
}
}
...
Fiddle Example
That being said you can shorten this code quite a bit, removing unneeded looping and work you can shorten all your code to simply:
for (var key in rooms[room]) {
var item = rooms[room][key];
if(item.side == 2)
side2.push(item.loc)
}
Fiddle Example
From your statement, you want to push the value of loc property to the array side2 if the value of side property is 2.
But in your code
if(prop == 'loc') {
if(obj[prop] == 2) {
side2.push(key);
}
}
You are comparing the value of loc property to be 2, not the value of side property. you probably need something like
if(prop == 'side') {
if(obj[prop] == 2) {
side2.push(obj['loc']);
}
}
As mentioned in comments and other answers, you are looking for a loc property of 2 which doesn't exist. So the immediate problem can be solved by replacing loc with side (assuming that's what you want).
But your code can be simplified. Looping at the top level is fine. However, the entire nested loop part of your code:
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
if(prop == 'loc') {
if(obj[prop] == 2) {
side2.push(key);
}
}
}
}
can be replaced with
if (obj.side == 2) side2.push(key);
In other words, you don't need to loop through an object's properties to find a particular one (side in this case). You can just access it, with obj.side.
You can also conceive of this problem as wanting to filter the list of rooms down to those with people with a loc of 2, in which case you could write:
Object.keys(rooms) . filter(hasPeopleWithLoc(2))
where
function hasPeopleWithLoc(loc) {
return function(roomKey) {
var room = rooms[roomKey];
return Object.keys(room) . some(function(personKey) {
return room[personKey].loc === loc;
});
};
}
Note that this code will leave you with just one entry for a room in the result if anyone in that room has a loc of 2. Your original code behaves slightly differently; it puts an entry for the room in the result for each person in that room with the desired loc.
I have a JSON object like this...
{
"tasks":[
{
"id":"task_3",
"taskName":"Task A",
"assignee":"Barrack Obama",
"timeReqOptimisitic":"4",
"timeReqNormal":"8",
"timeReqPessimistic":"14",
"timeUnit":"Days",
"timeReq":"8.33",
"positionX":493,
"positionY":101,
"lockStatus":"unlocked"
}
],
"milestones":[
{
"id":"task_1",
"milestoneName":"Start",
"positionX":149,
"positionY":109,
"lockStatus":"unlocked",
"milestoneDate":"2015-04-07"
},
{
"id":"task_2",
"milestoneName":"Finish",
"positionX":989,
"positionY":367,
"lockStatus":"unlocked",
"milestoneDate":"2015-04-22"
}
],
"connections":[
{
"connectionId":"con_10",
"pageSourceId":"task_1",
"pageTargetId":"task_3"
},
{
"connectionId":"con_20",
"pageSourceId":"task_3",
"pageTargetId":"task_2"
}
]
}
...this is a minimal version. In practice, there are numerous items in "tasks", "milestones" and "connections".
I need to iterate through the object and determine the "id" of the "milestones" item with the lowest/earliest "milestoneDate", then identify the "connections" item that has the same value for its "pageSourceId" and return its "pageTargetId".
So in the above example:
Step 1) Iterate through the object and determine the "id" of the "milestones" item with the lowest/earliest "milestoneDate".
Answer: milestones.id = "task_1"
Step 2) Identify the "connections" item that has the same value for its "pageSourceId".
Answer: connections.pageSourceId = "task_1"
Step 3) Return its "pageTargetId".
Answer: "task_3"
I have a working example here. However, I would like to know if there is a way to accomplish this without using the extremely high start date and also in one loop.
As you are not parsing the same array on these two loops, there is no way to merge your loops.
Anyway, you can yet remove the loops to access to the arrays:
http://jsfiddle.net/gael/sruvtwre/2/
$.each(object.milestones, function( index, value ) {
if(startDate > parseDate(value.milestoneDate)) {
startDate = parseDate(value.milestoneDate);
id = value.id
}
});
$.each(object.connections, function( index, value ) {
if(id == value.pageSourceId) {
pageTargetId = value.pageTargetId;
}
});
May be also sorting, and indexing your datas. Then you would need no loops:
Elements in milestones should be sorted, so the earliest milestones element would be milestones[0].
Elements in connections should be indexed by their pageTargetId property, so the requested element should be connections[id].
Your two loops would become:
var pageTargetId= object.connections[ object.milestones[0].id ].pageTargetId;
http://jsfiddle.net/gael/sruvtwre/4/
As said in comments, sorting is not an optimal solution, even if that does not really matter for small sets.
Roughly, there is no no needs to sort all the datas, just the latest matters.
You can use array reduce method, as an comparable alternative to a simple loop:
var latestMilestone= object.milestones.reduce(function(milestone1, milestone2){
if( parseDate(milestone1.milestoneDate) > parseDate(milestone2.milestoneDate) )
return milestone1;
else
return milestone2;
//convert date to timestamp
function parseDate(date) {
var parts = date.split('-');
return Date.UTC(parts[0], parts[1]-1, parts[2]); // Note: months are 0-based
}
});
How about this:
Assuming you get the milestones.id = "task_1" in first loop; outside the loop we can have use jQuery grep. As connections will have unique pageSourceId, grep will return an array with only one object.
var filteredData = jQuery.grep('CONNECTIONS_ARRAY', function(element, index){
return element.pageSourceId == 'MILESTONES_ID'; // Which you get in the loop earlier
});
Then we can access pageTargetId like this:
if(filteredData.length){
filteredData[0].pageTargetId;
}
Try
var dates = []
, ids = []
, filtered = $.map(data.milestones, function(value, index) {
dates.push(new Date(value.milestoneDate).getTime());
ids.push(value.id);
if (dates.length === data.milestones.length) {
var id = ids[$.inArray(Math.min.apply(Math, dates), dates)]
, res = $.grep(data.connections, function(task, key) {
return task.pageSourceId === id
})[0].pageTargetId;
return res
}
})[0]; // `"task_3"`
var data = {
"tasks":[
{
"id":"task_3",
"taskName":"Task A",
"assignee":"Barrack Obama",
"timeReqOptimisitic":"4",
"timeReqNormal":"8",
"timeReqPessimistic":"14",
"timeUnit":"Days",
"timeReq":"8.33",
"positionX":493,
"positionY":101,
"lockStatus":"unlocked"
}
],
"milestones":[
{
"id":"task_1",
"milestoneName":"Start",
"positionX":149,
"positionY":109,
"lockStatus":"unlocked",
"milestoneDate":"2015-04-07"
},
{
"id":"task_2",
"milestoneName":"Finish",
"positionX":989,
"positionY":367,
"lockStatus":"unlocked",
"milestoneDate":"2015-04-22"
}
],
"connections":[
{
"connectionId":"con_10",
"pageSourceId":"task_1",
"pageTargetId":"task_3"
},
{
"connectionId":"con_20",
"pageSourceId":"task_3",
"pageTargetId":"task_2"
}
]
};
var dates = []
, ids = []
, filtered = $.map(data.milestones, function(value, index) {
dates.push(new Date(value.milestoneDate).getTime());
ids.push(value.id);
if (dates.length === data.milestones.length) {
var id = ids[$.inArray(Math.min.apply(Math, dates), dates)]
, res = $.grep(data.connections, function(task, key) {
return task.pageSourceId === id
})[0].pageTargetId;
return res
}
})[0];
document.write(filtered);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
I have some json : data.
I have a string build that looks like this:
sections.1.subsections.0.items.0.citation.paragraph
What I need to do is manipulate that string to be able to access that value in data. So turn it into something usable:
data['sections'][1]['subsections'][0]['items'][0]['citation']['paragraph']
And then use it to change that value in data. So:
data['sections'][1]['subsections'][0]['items'][0]['citation']['paragraph'] = 'new value'
I can split the original string on the . and I think that gets me somewhere but I'm not at all sure how to then re-use the parts to allow me access to that value in data.
Thanks!
I'm still not quite sure why you're handling the JSON in this fashion but if it has to be done this way, then you'll need to use recursion to access the data. Assuming I mapped your object correctly, the example below should provide you with a method for doing this:
var data = {
sections: [
{
subsections: []
},
{
subsections: [
{
items: [
{
citation: {
paragraph: "Citation by Warlock"
}
}
]
}
]
}
]
};
var string = "sections.1.subsections.0.items.0.citation.paragraph",
parts = string.split('.');
function getValue(tree, index) {
if(index < (parts.length - 1)) {
return getValue(tree[parts[index]], index + 1);
} else {
return tree[parts[index]];
}
}
function setValue(tree, index, newValue) {
if(index < (parts.length - 1)) {
setValue(tree[parts[index]], index + 1, newValue);
} else {
tree[parts[index]] = newValue;
}
}
alert(getValue(data, 0));
setValue(data, 0, "New Citation By Warlock");
alert(getValue(data, 0));
The idea is that the getValue(...); function steps one layer deep into your JSON and then recursively calls itself. This allows the data to be accessed one step at a time until the last part is retrieved. The value is then returned via the recursion in all the previous function calls.
The same idea is true for setting the value. The setValue(...); function steps into the JSON one layer at a time passing the new value to set until it's reached the last nested layer. The value is then set for the specified property.
EDIT:
A better implementation would be to pass the parts array into the getValue(...); and setValue(...); function to eliminate external dependencies. Then, within the function shift the array's data values to step through the nested layers. This eliminates the need for index tracking based on the original array's values:
var data = {
sections: [
{
subsections: []
},
{
subsections: [
{
items: [
{
citation: {
paragraph: "Citation by Warlock"
}
}
]
}
]
}
]
};
var string = "sections.1.subsections.0.items.0.citation.paragraph",
parts = string.split('.');
function getValue(temp, tree) {
if(temp.length > 1) {
tree = tree[temp[0]];
temp.shift();
return getValue(temp, tree);
} else {
return tree[temp[0]];
}
}
function setValue(temp, tree, newValue) {
if(temp.length > 1) {
tree = tree[temp[0]];
temp.shift();
setValue(temp, tree, newValue);
} else {
tree[temp[0]] = newValue;
}
}
alert(getValue(parts, data));
setValue(parts, data, "New Citation By Warlock");
alert(getValue(parts, data));
I have the following JSON -
{
"node1":[
{
"one":"foo",
"two":"foo",
"three":"foo",
"four":"foo"
},
{
"one":"bar",
"two":"bar",
"three":"bar",
"four":"bar"
},
{
"one":"foo",
"two":"foo",
"three":"foo",
"four":"foo"
}
],
"node2":[
{
"link":"baz",
"link2":"baz"
},
{
"link":"baz",
"link2":"baz"
},
{
"link":"qux",
"link2":"qux"
},
]
};
I have the following javascript that will remove duplicates from the node1 section -
function groupBy(items, propertyName) {
var result = [];
$.each(items, function (index, item) {
if ($.inArray(item[propertyName], result) == -1) {
result.push(item[propertyName]);
}
});
return result;
}
groupBy(catalog.node1, 'one');
However this does not account for dupicates in node2.
The resulting JSON I require is to look like -
{
"node1":[
{
"one":"foo",
"two":"foo",
"three":"foo",
"four":"foo"
},
{
"one":"bar",
"two":"bar",
"three":"bar",
"four":"bar"
}
],
"node2":[
{
"link":"baz",
"link2":"baz"
},
{
"link":"qux",
"link2":"qux"
},
]
};
However I cannot get this to work and groupBy only returns a string with the duplicates removed not a restructured JSON?
You should probably look for some good implementation of a JavaScript set and use that to represent your node objects. The set data structure would ensure that you only keep unique items.
On the other hand, you may try to write your own dedup algorithm. This is one example
function dedup(data, equals){
if(data.length > 1){
return data.reduce(function(set, item){
var alreadyExist = set.some(function(unique){
return equals(unique, item);
});
if(!alreadyExist){
set.push(item)
}
return set;
},[]);
}
return [].concat(data);
}
Unfortunately, the performance of this algorithm is not too good, I think somewhat like O(n^2/2) since I check the set of unique items every time to verify if a given item exists. This won't be a big deal if your structure is really that small. But at any rate, this is where a hash-based or a tree-based algorithm would probably be better.
You can also see that I have abstracted away the definition of what is "equal". So you can provide that in a secondary function. Most likely the use of JSON.stringify is a bad idea because it takes time to serialize an object. If you can write your own customized algorithm to compare key by key that'd be probably better.
So, a naive (not recommended) implementation of equals could be somewhat like the proposed in the other answer:
var equals = function(left, right){
return JSON.stringify(left) === JSON.stringify(right);
};
And then you could simply do:
var res = Object.keys(source).reduce(function(res, key){
res[key] = dedup(source[key], equals);
return res;
},{});
Here is my version:
var obj = {} // JSON object provided in the post.
var result = Object.keys(obj);
var test = result.map(function(o){
obj[o] = obj[o].reduce(function(a,c){
if (!a.some(function(item){
return JSON.stringify(item) === JSON.stringify(c); })){
a.push(c);
}
return a;
},[]); return obj[o]; });
console.log(obj);//outputs the expected result
Using Array.prototype.reduce along with Array.prototype.some I searched for all the items being added into the new array generated into Array.prototype.reduce in the var named a by doing:
a.some(function(item){ return JSON.stringify(item) === JSON.stringify(c); })
Array.prototype.some will loop trough this new array and compare the existing items against the new item c using JSON.stringify.
Try this:
var duplicatedDataArray = [];
var DuplicatedArray = [];
//Avoiding Duplicate in Array Datas
var givenData = {givenDataForDuplication : givenArray};
$.each(givenData.givenDataForDuplication, function (index, value) {
if ($.inArray(value.ItemName, duplicatedDataArray) == -1) {
duplicatedDataArray.push(value.ItemName);
DuplicatedArray.push(value);
}
});