This is my JSON data:
{
"EF": [
{
"OP": "op1",
"pound": 2000,
"Date": "2012-1-13T00:00:00.000Z"
},
{
"OP": "op1",
"pound": 1800,
"Date": "2014-12-6T00:00:00.000Z"
},
{
"OP": "op2",
"pound": 300,
"Date": "2013-6-1T00:00:00.000Z"
}
]
}
I want to Count each parameter value and Sort them from largest to smallest to have a table like this:
OP : op1 (2), OP2 (1) Pound: 2000, 1800, 300 Date:
2014-12-6T00:00:00.000Z, 2013-6-1T00:00:00.000Z,
2012-1-13T00:00:00.000Z
I tried to use d3.nest() but I didnot have much success with it. Any thoughts?
//JSON from db?
var json = {
"EF": [{
"OP": "op1",
"pound": 2000,
"Date": "2012-1-13T00:00:00.000Z"
}, {
"OP": "op1",
"pound": 1800,
"Date": "2014-12-6T00:00:00.000Z"
}, {
"OP": "op2",
"pound": 300,
"Date": "2013-6-1T00:00:00.000Z"
}]
};
//Sort based on pound
json.EF.sort(function(a, b) {
if (a.pound < b.pound) return 1;
if (a.pound > b.pound) return -1;
return 0;
});
var hash = {}; //Keep track of counts
//Count the values
for (var i in json.EF) {
var obj = json.EF[i];
if (hash[obj.OP]) {
hash[obj.OP] += 1;
} else {
hash[obj.OP] = 1;
}
}
//Sorted
console.log("SORTED:", json);
console.log("COUNTS:", hash);
//Now, when you loop through the json to display the values, just check the counts and display them
Related
I'm trying to make a auto complete search bar using jquery autocomplete. The thing is I need to display Json data from an external site into my search bar.
Whenever I try to put the data as such from json into the script, it's working. But when I refer external url it refuses to work.
I tried implementing all json data into my script. But it takes so long to process as there will be more than 40000+ lines in my html page.
The Json link for the data which I have to display is here
<script>
$('#id_ticker').autocomplete({
source: function(request, response) {
var data = {
"success": true,
"data": [
{
"symbol": "AACG",
"name": "ATA Creativity Global American Depositary Shares",
"lastsale": "$2.19",
"netchange": "-0.45",
"pctchange": "-17.045%",
"volume": "1408435",
"marketCap": "68715455.00",
"country": "China",
"ipoyear": "",
"industry": "Service to the Health Industry",
"sector": "Miscellaneous",
"url": "/market-activity/stocks/aacg"
},
{
"symbol": "AACI",
"name": "Armada Acquisition Corp. I Common Stock",
"lastsale": "$9.88",
"netchange": "0.01",
"pctchange": "0.101%",
"volume": "8345",
"marketCap": "204609860.00",
"country": "United States",
"ipoyear": "2021",
"industry": "",
"sector": "",
"url": "/market-activity/stocks/aaci"
}],
"additional_data": {
"pagination": {
"start": 0,
"limit": 5,
"more_items_in_collection": true,
"next_start": 5
}
}
};
var datamap = data.data.map(function(i) {
return {
label: i.symbol + ' - ' + i.name.split(' ').slice(0, 2).join(' '),
value: i.symbol,
desc: i.title
}
});
var key = request.term;
datamap = datamap.filter(function(i) {
return i.label.toLowerCase().indexOf(key.toLowerCase()) >= 0;
});
response(datamap);
},
minLength: 1,
delay: 500
});
</script>
The above code works and the below code doesn't.
<script>
$('#id_ticker').autocomplete({
source: function(request, response) {
var data = {
"success": true,
"data": ["https://raw.githubusercontent.com/rreichel3/US-Stock-Symbols/main/nyse/nyse_full_tickers.json"
],
"additional_data": {
"pagination": {
"start": 0,
"limit": 5,
"more_items_in_collection": true,
"next_start": 5
}
}
};
var datamap = data.data.map(function(i) {
return {
label: i.symbol + ' - ' + i.name.split(' ').slice(0, 2).join(' '),
value: i.symbol,
desc: i.title
}
});
var key = request.term;
datamap = datamap.filter(function(i) {
return i.label.toLowerCase().indexOf(key.toLowerCase()) >= 0;
});
response(datamap);
},
minLength: 1,
delay: 500
});
</script>
Looking for a solution to add this and also for a solution to reduce the json key pair with only "symbol" and "name" from each corresponding data in the link.
Try this:
function toAutocomplete(dt, keyvar){
let rli = [];
for (let i = 0; i < dt.length; i++) rli.push(dt[i][keyvar]);
return rli;
}
function inArrayAutocompleteSelected(key, array_autocomplete, array_master){
let x = array_master[$.inArray(key, array_autocomplete)];
return x;
}
$('#id_ticker').autocomplete({ source: [], minLength: 1 });
// $('#id_ticker').autocomplete("disable");
let url = 'https://raw.githubusercontent.com/rreichel3/US-Stock-Symbols/main/nyse/nyse_full_tickers.json';
let r = _ajax('GET', url, ''); // your ajax script
console.log(r);
let liAuto = toAutocomplete(r, 'name');
console.log(liAuto);
$('#id_ticker').autocomplete("option", "source", liAuto );
// $('#id_ticker').autocomplete("enable");
$("#id_ticker").autocomplete({
select: function( event, ui ) {
console.log(ui, ui.item);
getData = inArrayAutocompleteSelected(ui.item.value, liAuto, r);
console.log(getData);
}
});
I would like produce a list of grouped JSON elements according to a specific criteria, but I am unable to make my loop work.
The function should make groups of with 12 bottles and return a single JSON list. So in this example, the function should extract the 3 first items and then run again to extract the remaining ones. But I am looping forever... Thank you in advance,
var data = {
"order": [
{ "product": "MAXIMUS", "quantity": "3" },
{ "product": "COLECCION", "quantity": "3" },
{ "product": "CABERNET FRANC", "quantity": "6" },
{ "product": "CHARDONNAY", "quantity": "6" },
{ "product": "SAUVIGNON BLANC", "quantity": "6" }
]
};
var qtd = data.order;
var size = qtd.length;
var addline = '';
var add = '';
var total = 0;
var i = 0;
var a = 0;
var c = '';
function MakeList(i, add) {
for (i < 0; total < 12; i++) {
total += parseInt(qtd[i].quantity);
addline = addline + '{' + '"quantity": "' + qtd[i].quantity + ' units"},';
i = i++;
add = '{"Box of 12":[' + addline.slice(0, -1) + "]}";
}
return [i, add];
}
function BuildLabels(i, add) {
for (i < 0; c = "true"; i++) {
c = a[0] < size;
a += MakeList(i, add);
i = i++;
}
return a;
}
var results = BuildLabels(i, add);
output = { id: 3, results };
for (i < 0; c = "true"; i++)
something weird is happening here. You don't set any condition on cycle to stop, you just assign value "true" to c. Try to use == instead of =; also initialization looks strange - set i to 0. Apparently, It will make the whole thing work (at least the loop will stop at some point), but in the end I get that the variable results is equal to 0. There are other mistakes/weird stuff out there. Propably, you wanted to achieve something like this:
var data = {
"order": [
{ "product": "MAXIMUS", "quantity": "3" },
{ "product": "COLECCION", "quantity": "3" },
{ "product": "CABERNET FRANC", "quantity": "6" },
{ "product": "CHARDONNAY", "quantity": "6" },
{ "product": "SAUVIGNON BLANC", "quantity": "6" }
]
};
function MakeList(data) {
var selected = [], bottlesNum = 0;
for (var i = 0; bottlesNum < 12; i++) {
selected.push(data.order[i]);
bottlesNum += parseInt(data.order[i].quantity);
}
return selected;
}
var results = MakeList(data);
// now it is a JS object:
console.log({ id: 3, results: results });
// if you want it to be a JSON string, use JSON.stringify():
console.log(JSON.stringify({ id: 3, results: results }));
check it out.
UPDATE
var data = {
"order": [
{ "product": "MAXIMUS", "quantity": "3" },
{ "product": "COLECCION", "quantity": "3" },
{ "product": "CABERNET FRANC", "quantity": "6" },
{ "product": "CHARDONNAY", "quantity": "6" },
{ "product": "SAUVIGNON BLANC", "quantity": "6" }
]
};
function makeGroup(data, max) {
var selected = [], bottlesNum = 0;
while(data.order.length) {
if(bottlesNum + +data.order[0].quantity > max) break;
var order = data.order.shift();
bottlesNum += +order.quantity; // casting to Number
selected.push(order);
}
return selected;
}
function splitOrder(data, max) {
while(data.order.length) {
var results = makeGroup(data, max);
if(!results.length) {
console.log("Error: a product's quantity is greater than max. size of the group. Try to increase max. size of the group.");
break;
}
console.log({ results: results });
}
}
// 2nd argument - max. size of the group. In case of 12 there will be 2 groups - of 3, 3, 6 and 6, 6 bottles
splitOrder(data, 12);
// Also notice that if max. size of the group is a changing value and can be set somehow to, lets say, 4 which is fewer than number of some products (6) in our order. So, it is impossible to complete such a task without taking some additional steps to handle this situation. For example, we could filter our data beforehand to exclude products with numbars greater than 4 and then form groups based on the rest of the data. Or we can treat products with number equal to 6 as if they satisfy our constraint etc.
I have an array with objects, like the following.
b = {
"issues": [{
"fields": {
"status": {
"id": "200",
"name": "Backlog"
}
}
}, {
"fields": {
"status": {
"id": "202",
"name": "close"
}
}
}, {
"fields": {
"status": {
"id": "201",
"name": "close"
}
}
}]
};
I want to count how many issues have status close, and how many have backlog. I'd like to save the count in a new array as follows.
a = [
{Name: 'Backlog', count: 1},
{Name: 'close', count: 2}
];
I have tried the following.
b.issues.forEach(function(i) {
var statusName = i.fields.status.name;
if (statusName in a.Name) {
a.count = +1;
} else {
a.push({
Name: statusName,
count: 1
});
}
});
That however doesn't seem to be working. How should I implement this?
This is a perfect opportunity to use Array#reduce. That function will take a function that is applied to all elements of the array in order and can be used to accumulate a value. We can use it to accumulate an object with the various counts in it.
To make things easy, we track the counts in an object as simply {name: count, otherName: otherCount}. For every element, we check if we already have an entry for name. If not, create one with count 0. Otherwise, increment the count. After the reduce, we can map the array of keys, stored as keys of the object, to be in the format described in the question. See below.
var b = {
"issues": [{
"fields": {
"status": {
"id": "200",
"name": "Backlog"
}
}
}, {
"fields": {
"status": {
"id": "202",
"name": "close"
}
}
}, {
"fields": {
"status": {
"id": "201",
"name": "close"
}
}
}]
};
var counts = b.issues.reduce((p, c) => {
var name = c.fields.status.name;
if (!p.hasOwnProperty(name)) {
p[name] = 0;
}
p[name]++;
return p;
}, {});
console.log(counts);
var countsExtended = Object.keys(counts).map(k => {
return {name: k, count: counts[k]}; });
console.log(countsExtended);
.as-console-wrapper {
max-height: 100% !important;
}
Notes.
Array#reduce does not modify the original array.
You can easily modify the function passed to reduce to for example not distinguish between Backlog and backlog by changing
var name = c.fields.status.name;
into
var name = c.fields.status.name.toLowerCase();
for example. More advanced functionality can also easily be implemented.
Using ES6 Arrow functions you can do it with minimum syntax
var b = {
"issues": [{
"fields": {
"status": {
"id": "200",
"name": "Backlog"
}
}
}, {
"fields": {
"status": {
"id": "202",
"name": "close"
}
}
}, {
"fields": {
"status": {
"id": "201",
"name": "close"
}
}
}]
};
var countOfBackLog = b.issues.filter(x => {
return x.fields.status.name === "Backlog"
}).length
var countOfClose = b.issues.filter(x => {
return x.fields.status.name === "close"
}).length
a =[{Name: 'Backlog', count : countOfBackLog}, {Name: 'close', count : countOfClose}]
More about arrow functions here
You can write like this. It is dynamic.
var a = {};
for(var key in b["issues"]){
if(!a.hasOwnProperty(b["issues"][key].fields.status.name)){
a[b["issues"][key].fields.status.name] = 1;
}else{
a[b["issues"][key].fields.status.name] = a[b["issues"][key].fields.status.name]+1;
}
}
var c = [];
for(var key1 in a){
c.push({
name : key1,
count : a[key1]
});
}
Something like this should do the trick. Simply iterate over your data, keep 2 counters with the number of each type of issue, and create the data format you want in the end. Try it live on jsfiddle.
var b = {
"issues": [{
"fields": {
"status": {
"id": "200",
"name": "Backlog"
}
}
}, {
"fields": {
"status": {
"id": "202",
"name": "close"
}
}
}, {
"fields": {
"status": {
"id": "201",
"name": "close"
}
}
}]
};
var data = [];
for(var issue of b.issues){
var entryFound = false;
var tempObj = {
name: issue.fields.status.name,
count: 1
};
for(var item of data){
if(item.name === tempObj.name){
item.count++;
entryFound = true;
break;
}
}
if(!entryFound){
data.push(tempObj);
}
}
console.log(data);
This question already has answers here:
reduce array to a by grouping objects with same property
(2 answers)
Closed 6 years ago.
I have an object as:
[
{
"DATA": "2016-01-22",
"TOTAL": "7"
},
{
"DATA": "2016-01-25",
"TOTAL": "3"
},
{
"DATA": "2016-01-26",
"TOTAL": "1"
},
{
"DATA": "2016-01-27",
"TOTAL": "2"
},
{
"DATA": "2016-01-22",
"TOTAL": "1"
},
{
"DATA": "2016-01-25",
"TOTAL": "1"
},
{
"DATA": "2016-01-27",
"TOTAL": "1"
},
...
]
How can I shrink it down to something like below, this is, concatenate/join the TOTAL keys where the date is the same and fill with 0 in case the date doesn't repeat?:
[
{
"DATA": "2016-01-22",
"TOTAL": ["7", "1"]
},
{
"DATA": "2016-01-25",
"TOTAL": ["3", "1"]
},
{
"DATA": "2016-01-26",
"TOTAL": ["1", "0"]
},
{
"DATA": "2016-01-27",
"TOTAL": ["2", "1"]
}
]
I've been trying with this block of code, but can't get TOTAL keys all the same dimension - filled with zeros would be fine.
var output = [];
d.forEach(function(value) {
var existing = output.filter(function(v, i) {
return v.DATA == value.DATA;
});
if (existing.length) {
var existingIndex = output.indexOf(existing[0]);
output[existingIndex].TOTAL = output[existingIndex].TOTAL.concat(value.TOTAL);
} else {
if (typeof value.TOTAL == 'string')
value.TOTAL = [value.TOTAL];
output.push(value);
}
});
console.log(JSON.stringify(output, null, 4));
var someData = [] // <- your instantiated array in question.
var transformedData = [];
var highestCount = 0;
someData.forEach(x => {
var foundIndex = transformedData.findIndex((ele) => ele.DATA === x.DATA);
if (foundIndex < 0) {
transformedData
.push({DATA : x.DATA, TOTAL : [x.TOTAL]});
} else {
transformedData[foundIndex]
.TOTAL.push(x.TOTAL);
var currentCountAtIndex = transformedData[foundIndex].TOTAL.length;
if (highestCount < transformedData[foundIndex].TOTAL.length) highestCount = currentCountAtIndex;
}
});
// fill any indicies in array that are lower than the highest count with 0
transformedData
.forEach(x => {
if (x.TOTAL.length < highestCount) {
while(x.TOTAL.length < highestCount) {
x.TOTAL.push(0);
}
}
});
It could be as simple as this:
var result = {};
var test = [
{
"DATA": "2016-01-22",
"TOTAL": "7"
},
{
"DATA": "2016-01-25",
"TOTAL": "3"
},
{
"DATA": "2016-01-26",
"TOTAL": "1"
},
{
"DATA": "2016-01-27",
"TOTAL": "2"
},
{
"DATA": "2016-01-22",
"TOTAL": "1"
},
{
"DATA": "2016-01-25",
"TOTAL": "1"
},
{
"DATA": "2016-01-27",
"TOTAL": "1"
}];
console.log("test array: ", test);
var len = 0,
sorted;
// Flatten the object.
test.forEach( d => {
result[d.DATA] == undefined ? result[d.DATA] = [d.TOTAL] : result[d.DATA].push(d.TOTAL);
});
// Sort so we get the max length to know how many zeros to add.
sorted = Object.keys(result).sort( (k, b) => {
return result[k].length - result[b].length;
});
// Max length from the sorted array.
len = result[sorted[sorted.length - 1]].length;
// push zeros
Object.keys(result).forEach( k => {
if(result[k].length < len){
for(var i = result[k].length; i < len; i++){
result[k].push("0");
}
}
});
console.log("result: ", result);
I have a JSON data like
{
"data": [{
"distance": "700",
"name": "xyz"
}, {
"distance": "680",
"name": "abc"
}, {
"distance": "670",
"name": "lmn"
}, {
"distance": "620",
"name": "pqr"
}, {
"distance": "400",
"name": "tuv"
}]
}
I want to find the maximum & minimum distance between two consecutive nodes.
I tried following code but I don't know what I'm missing
Here I'm trying to make use of jQuery sort to achieve it.
var min = data[0].distance - data[1].distance,
max = data[0].distance - data[1].distance;
data.sort(function (a, b) {
var temp = a.distance - b.distance;
if (temp > max)
max = temp;
if (temp < min)
min = temp;
});
I even tried using normal jQuery forEach loop
var min = data[0].distance - data[1].distance,
max = data[0].distance - data[1].distance;
data.forEach(function (d, i) {
var temp = data[i + 1].distance - d.distance;
if (temp > max)
max = temp;
if (temp < min)
min = temp;
});
You can do it something like this:
// Set default values to the max and min, to compare them later
var min = Number.MAX_VALUE,
max = Number.MIN_VALUE;
// Iterate over the data object
for (var i = obj.data.length - 2; i >= 0; i--) {
// Get the absolute(ignoring negatives) difference
var temp = Math.abs(obj.data[i].distance - obj.data[i + 1].distance);
// update values accordingly
min = Math.min(min, temp);
max = Math.max(max, temp);
}
console.log(min, max);
var obj = {
"data": [{
"distance": "700",
"name": "xyz"
}, {
"distance": "680",
"name": "abc"
}, {
"distance": "670",
"name": "lmn"
}, {
"distance": "620",
"name": "pqr"
}, {
"distance": "400",
"name": "tuv"
}]
};
var min = Number.MAX_VALUE,
max = Number.MIN_VALUE;
for (var i = obj.data.length - 2; i >= 0; i--) {
var temp = Math.abs(obj.data[i].distance - obj.data[i + 1].distance);
min = Math.min(min, temp);
max = Math.max(max, temp);
}
console.log(min, max);
try it.
var jsonData = {
"data": [{
"distance": "700",
"name": "xyz"
}, {
"distance": "680",
"name": "abc"
}, {
"distance": "670",
"name": "lmn"
}, {
"distance": "620",
"name": "pqr"
}, {
"distance": "400",
"name": "tuv"
}]
};
var maxData = 0;
var minData = 0;
var data = 0;
$.each(jsonData.data, function(i, obj) {
if(i==0)
{
minData = obj.distance;
}
else
{
data = jsonData.data[i-1].distance - obj.distance;
if(data > maxData)
maxData = data;
if(data < minData)
minData = data;
}
});
console.log("Max : "+maxData);
console.log("Min : "+minData);