how to find minimum and maximum value in object literal by javascript - javascript

I want to get minimum value from object literal and want to use it in anuglarjs i.e., :-
scope.data = {
'studentName' : "Anand",
'socialStudies' : "98",
'english' : "90",
'math' : "80"
};
Initially it will be single object but after adding more data it will be just like array data. So I want to find out each row minimum and maximum value.
I have already try below code for min and max but didn't get the solution as its giving me "NaN".
var maxVal = Math.max.apply(Math,scope.data);
Please suggest some good option. I am using it in angularjs.
Waiting for your response.
My entire piece of code is as under :-
scope.save = function (item){
scope.person = {
'name' : scope.person.name,
'hindi' : scope.person.hindi,
'english' : scope.person.english,
'math' : scope.person.math
};
if(typeof rootScope.students === 'undefined'){
rootScope.students = [];
rootScope.students.push(scope.person);
}else{
rootScope.students.push(scope.person);
}
location.path("/");
}

Here's one way to do it that checks only numeric looking properties and returns both the max and min values and their corresponding property names (since I assume that would be useful to know):
scope.data = {
'studentName' : "Anand",
'socialStudies' : "98",
'english' : "90",
'math' : "80"
};
function findMaxMin(obj) {
var max = Number.MIN_VALUE, min = Number.MAX_VALUE, val;
var maxProp, minProp;
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
val = +obj[prop];
if (!isNaN(val)) {
if (val > max) {
maxProp = prop;
max = val;
}
if (val < min) {
minProp = prop;
min = val;
}
}
}
}
// if no numeric looking properties, then return null
if (!maxProp) {
return null;
}
return {minVal: min, minProp: minProp, maxVal: max, maxProp: maxProp};
}
Working demo: http://jsfiddle.net/jfriend00/q81g6ehb/
And, if you want to use this on an array, you can just call it for each array element:
function findMaxMinArray(arr) {
var results = [];
for (var i = 0; i < arr.length; i++) {
var m = findMaxMin(arr[i]);
m.obj = arr[i];
results.push(m);
}
return results;
}
Working demo: http://jsfiddle.net/jfriend00/uv50y3e8/
If you wanted it to auto-detect whether an array was past in or not and just always return an array of results, you could do this:
function findMaxMinAny(obj) {
var results = [];
if (Array.isArray(obj)) {
for (var i = 0; i < arr.length; i++) {
var m = findMaxMin(arr[i]);
m.obj = arr[i];
results.push(m);
}
} else {
// only a single object
results.push(findMaxMin(obj));
}
return results;
}

Use jQuery.map() to translate items into new array, if the callback returns null or undefined that item will not be included. You can use that to filter the result ( for example, to remove the non numeric values ).
var data = {
'studentName' : "Anand",
'socialStudies' : "98",
'english' : "90",
'math' : "80"
};
var array = $.map( data, function( val ) {
return $.isNumeric( val ) ? val : null;
});
console.log( Math.max.apply( null, array ) ); // 98

Related

Need guidance to amend excel to JSON javascript code to output one JSON per set of data

I'm not from a programming background but I have a requirement in that I need to be able to convert excel data to JSON format.
I have found the below package which is exactly what I need as I can control the object types from the header names rather than hard code for each field. It also allows me to column orientate my data i.e. the header in column A.
The package can be found here --> excel-as-json
The output looks like this:
[
{
"firstName": "Jihad",
"lastName": "",
"address": {
"street": "12 Beaver Court",
"city": "",
"state": "CO",
"zip": "81615"
},
"isEmployee": true,
"phones": [
{
"type": "home",
"number": "123.456.7890"
},
{
"type": "work",
"number": "098.765.4321"
}
],
"aliases": [
"stormagedden",
"bob"
]
},
{
"firstName": "Marcus",
"lastName": "Rivapoli",
"address": {
"street": "16 Vail Rd",
"city": "Vail",
"state": "CO",
"zip": "75850"
},
"isEmployee": false,
"phones": [
{
"type": "home",
"number": "123.456.7891"
},
{
"type": "work",
"number": "098.765.4322"
}
],
"aliases": [
"mac",
"markie"
]
}
]
What I need to do and what I'm struggling with is two fold:
I need to remove the square brackets from the beginning and end of the generated JSON
I need to be able to generate multiple JSONs i.e. a JSON for each column of data. So if I have data in column B and C, I need it to generate 2 JSON files with different names (ideally with the name of a specific attribute value)
The code is:
// Generated by CoffeeScript 2.2.4
(function() {
// Create a list of json objects; 1 object per excel sheet row
// Assume: Excel spreadsheet is a rectangle of data, where the first row is
// object keys and remaining rows are object values and the desired json
// is a list of objects. Alternatively, data may be column oriented with
// col 0 containing key names.
// Dotted notation: Key row (0) containing firstName, lastName, address.street,
// address.city, address.state, address.zip would produce, per row, a doc with
// first and last names and an embedded doc named address, with the address.
// Arrays: may be indexed (phones[0].number) or flat (aliases[]). Indexed
// arrays imply a list of objects. Flat arrays imply a semicolon delimited list.
// USE:
// From a shell
// coffee src/excel-as-json.coffee
var BOOLTEXT, BOOLVALS, _DEFAULT_OPTIONS, _validateOptions, assign, convert, convertValue, convertValueList, excel, fs, isArray, parseKeyName, path, processFile, transpose, write,
indexOf = [].indexOf;
fs = require('fs');
path = require('path');
excel = require('excel');
BOOLTEXT = ['true', 'false'];
BOOLVALS = {
'true': true,
'false': false
};
isArray = function(obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
};
// Extract key name and array index from names[1] or names[]
// return [keyIsList, keyName, index]
// for names[1] return [true, keyName, index]
// for names[] return [true, keyName, undefined]
// for names return [false, keyName, undefined]
parseKeyName = function(key) {
var index;
index = key.match(/\[(\d+)\]$/);
switch (false) {
case !index:
return [true, key.split('[')[0], Number(index[1])];
case key.slice(-2) !== '[]':
return [true, key.slice(0, -2), void 0];
default:
return [false, key, void 0];
}
};
// Convert a list of values to a list of more native forms
convertValueList = function(list, options) {
var item, j, len, results;
results = [];
for (j = 0, len = list.length; j < len; j++) {
item = list[j];
results.push(convertValue(item, options));
}
return results;
};
// Convert values to native types
// Note: all values from the excel module are text
convertValue = function(value, options) {
var testVal;
// isFinite returns true for empty or blank strings, check for those first
if (value.length === 0 || !/\S/.test(value)) {
return value;
} else if (isFinite(value)) {
if (options.convertTextToNumber) {
return Number(value);
} else {
return value;
}
} else {
testVal = value.toLowerCase();
if (indexOf.call(BOOLTEXT, testVal) >= 0) {
return BOOLVALS[testVal];
} else {
return value;
}
}
};
// Assign a value to a dotted property key - set values on sub-objects
assign = function(obj, key, value, options) {
var i, index, j, keyIsList, keyName, ref, ref1;
if (typeof key !== 'object') {
// On first call, a key is a string. Recursed calls, a key is an array
key = key.split('.');
}
// Array element accessors look like phones[0].type or aliases[]
[keyIsList, keyName, index] = parseKeyName(key.shift());
if (key.length) {
if (keyIsList) {
// if our object is already an array, ensure an object exists for this index
if (isArray(obj[keyName])) {
if (!obj[keyName][index]) {
for (i = j = ref = obj[keyName].length, ref1 = index; (ref <= ref1 ? j <= ref1 : j >= ref1); i = ref <= ref1 ? ++j : --j) {
obj[keyName].push({});
}
}
} else {
// else set this value to an array large enough to contain this index
obj[keyName] = (function() {
var k, ref2, results;
results = [];
for (i = k = 0, ref2 = index; (0 <= ref2 ? k <= ref2 : k >= ref2); i = 0 <= ref2 ? ++k : --k) {
results.push({});
}
return results;
})();
}
return assign(obj[keyName][index], key, value, options);
} else {
if (obj[keyName] == null) {
obj[keyName] = {};
}
return assign(obj[keyName], key, value, options);
}
} else {
if (keyIsList && (index != null)) {
console.error(`WARNING: Unexpected key path terminal containing an indexed list for <${keyName}>`);
console.error("WARNING: Indexed arrays indicate a list of objects and should not be the last element in a key path");
console.error("WARNING: The last element of a key path should be a key name or flat array. E.g. alias, aliases[]");
}
if (keyIsList && (index == null)) {
if (value !== '') {
return obj[keyName] = convertValueList(value.split(';'), options);
} else if (!options.omitEmptyFields) {
return obj[keyName] = [];
}
} else {
if (!(options.omitEmptyFields && value === '')) {
return obj[keyName] = convertValue(value, options);
}
}
}
};
// Transpose a 2D array
transpose = function(matrix) {
var i, j, ref, results, t;
results = [];
for (i = j = 0, ref = matrix[0].length; (0 <= ref ? j < ref : j > ref); i = 0 <= ref ? ++j : --j) {
results.push((function() {
var k, len, results1;
results1 = [];
for (k = 0, len = matrix.length; k < len; k++) {
t = matrix[k];
results1.push(t[i]);
}
return results1;
})());
}
return results;
};
// Convert 2D array to nested objects. If row oriented data, row 0 is dotted key names.
// Column oriented data is transposed
convert = function(data, options) {
var index, item, j, k, keys, len, len1, result, row, rows, value;
if (options.isColOriented) {
data = transpose(data);
}
keys = data[0];
rows = data.slice(1);
result = [];
for (j = 0, len = rows.length; j < len; j++) {
row = rows[j];
item = [];
for (index = k = 0, len1 = row.length; k < len1; index = ++k) {
value = row[index];
assign(item, keys[index], value, options);
}
result.push(item);
}
return result;
};
// Write JSON encoded data to file
// call back is callback(err)
write = function(data, dst, callback) {
var dir;
// Create the target directory if it does not exist
dir = path.dirname(dst);
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
return fs.writeFile(dst, JSON.stringify(data, null, 2), function(err) {
if (err) {
return callback(`Error writing file ${dst}: ${err}`);
} else {
return callback(void 0);
}
});
};
// src: xlsx file that we will read sheet 0 of
// dst: file path to write json to. If null, simply return the result
// options: see below
// callback(err, data): callback for completion notification
// options:
// sheet: string; 1: numeric, 1-based index of target sheet
// isColOriented: boolean: false; are objects stored in excel columns; key names in col A
// omitEmptyFields: boolean: false: do not include keys with empty values in json output. empty values are stored as ''
// TODO: this is probably better named omitKeysWithEmptyValues
// convertTextToNumber boolean: true; if text looks like a number, convert it to a number
// convertExcel(src, dst) <br/>
// will write a row oriented xlsx sheet 1 to `dst` as JSON with no notification
// convertExcel(src, dst, {isColOriented: true}) <br/>
// will write a col oriented xlsx sheet 1 to file with no notification
// convertExcel(src, dst, {isColOriented: true}, callback) <br/>
// will write a col oriented xlsx to file and notify with errors and parsed data
// convertExcel(src, null, null, callback) <br/>
// will parse a row oriented xslx using default options and return errors and the parsed data in the callback
_DEFAULT_OPTIONS = {
sheet: '1',
isColOriented: false,
omitEmptyFields: false,
convertTextToNumber: false
};
// Ensure options sane, provide defaults as appropriate
_validateOptions = function(options) {
if (!options) {
options = _DEFAULT_OPTIONS;
} else {
if (!options.hasOwnProperty('sheet')) {
options.sheet = '1';
} else {
if (!isNaN(parseFloat(options.sheet)) && isFinite(options.sheet)) {
if (options.sheet < 1) {
options.sheet = '1';
} else {
// could be 3 or '3'; force to be '3'
options.sheet = '' + options.sheet;
}
} else {
// something bizarre like true, [Function: isNaN], etc
options.sheet = '1';
}
}
if (!options.hasOwnProperty('isColOriented')) {
options.isColOriented = false;
}
if (!options.hasOwnProperty('omitEmptyFields')) {
options.omitEmptyFields = false;
}
if (!options.hasOwnProperty('convertTextToNumber')) {
options.convertTextToNumber = false;
}
}
return options;
};
processFile = function(src, dst, options = _DEFAULT_OPTIONS, callback = void 0) {
options = _validateOptions(options);
if (!callback) {
callback = function(err, data) {};
}
// NOTE: 'excel' does not properly bubble file not found and prints
// an ugly error we can't trap, so look for this common error first
if (!fs.existsSync(src)) {
return callback(`Cannot find src file ${src}`);
} else {
return excel(src, options.sheet, function(err, data) {
var result;
if (err) {
return callback(`Error reading ${src}: ${err}`);
} else {
result = convert(data, options);
if (dst) {
return write(result, dst, function(err) {
if (err) {
return callback(err);
} else {
return callback(void 0, result);
}
});
} else {
return callback(void 0, result);
}
}
});
}
};
// This is the single expected module entry point
exports.processFile = processFile;
// Unsupported use
// Exposing remaining functionality for unexpected use cases, testing, etc.
exports.assign = assign;
exports.convert = convert;
exports.convertValue = convertValue;
exports.parseKeyName = parseKeyName;
exports._validateOptions = _validateOptions;
exports.transpose = transpose;
}).call(this);
This is untested, but should get you close.
Try adding a function like this into the code (along with the other listed functions, like isArray, parseKeyName, etc.). Then in the processFile function, in the line return write(result, dst, function(err) {, replace write with writeEach.
See the comments in the code for clarification of what it's intended to do.
writeEach = function(data, dst, callback){
// Loops through columns, calling fs.writeFile for each one
data.forEach(function(person){ // argument name determines the name by which we will refer to the current column
var homePhoneDigits = person.phones[0]["number"].split(".").join(""); //removes `.` from phone number
var personDst = homePhoneDigits + ".json"; // uses digits of home phone as destination name
// pattern copied from 'write' function, with variable names changed
var dir;
dir = path.dirname(personDst);
if (!fs.existsSync(dir)) { fs.mkdirSync(dir); }
fs.writeFile(personDst, JSON.stringify(person, null, 2); //writes the current column to a file
});
return callback(void 0); // currently ignores any write errors
};

How to count the occurrence of each key within an array of objects?

Say I have an array of objects like so:
[{"taco":"","burrito":"","scone":"","beans":"true"},
{"taco":"true","burrito":"","scone":"true","beans":""},
{"taco":"true","burrito":"","scone":"","beans":""},
{"taco":"true","burrito":"","scone":"","beans":"true"}]
I need to count the occurrence of each element and return in it in an array
[3, 0, 1, 2]
any ideas would be appreciated, thanks!
I have attempted
var a = datasets.reduce(function (item, index) {
if (typeof item[index] == 'undefined') {
item[index] = 1;
} else {
item[index] += 1;
}
return item;
}, {});
could not get anything like that to work so i attempted converting it to json and then removing any key: value pairs with no value then counting remaining ones but have had no success with that either
function tableToJson(table) {
var data = [];
var headers = [];
for (var i=0; i < table[0].rows[0].cells.length; i++) {
headers[i] = table[0].rows[0].cells[i].innerHTML.toLowerCase().replace(/ /gi,'');
}
for (var i=1; i< table[0].rows.length; i++) {
var tableRow = table[0].rows[i];
var rowData = {};
for (var j=0; j<tableRow.cells.length; j++) {
rowData[ headers[j] ] = tableRow.cells[j].innerHTML;
}
data.push(rowData);
}
return data
}
function removeEmpty(jsonObj) {
var newObj = Object.getOwnPropertyNames(jsonObj);
for (var i = 0; i < newObj.length; i++) {
var value = newObj[i];
if (jsonObj[value] === null || jsonObj[value] === undefined) {
delete jsonObj[value];
}
}
}
You can try this
You can do it with reduce().
What i have done is first i check is the object property of current element if it is already in output object. If it's present than i check the value of current element property. if it is true than i increment the property of output object by 1.
If the object property of current element is not available in output than i check for the value of current element property. if it is true i assign output object property with value 1. if false i assign output object property with 0.
let obj = [{"taco":"","burrito":"","scone":"","beans":"true"},
{"taco":"true","burrito":"","scone":"true","beans":""},
{"taco":"true","burrito":"","scone":"","beans":""},
{"taco":"true","burrito":"","scone":"","beans":"true"}]
let op = obj.reduce((output,current)=>{
for(let key in current){
if( output[key] ){
if( current[key] ) output[key]+=1;
} else {
if( current[key] ){
output[key] = 1;
} else{
output[key] = 0;
}
}
}
return output;
},{})
console.log(op);
Try this:
var data = [{
taco: "",
burrito: "",
scone: "",
beans: "true"
},
{
taco: "true",
burrito: "",
scone: "true",
beans: ""
},
{
taco: "",
burrito, "true",
scone: "",
beans: "",
}, {
taco: "true",
burrito: "",
scone: "",
beans: "true"
}]
var total = [0, 0, 0, 0];
data.forEach(function(obj) {
if (obj.taco) {
total[0]++;
}
if (burrito) {
total[1]++;
}
if (obj.scone) {
total[2]++;
}
if (obj.beans) {
total[3]++;
}
})
console.log(total)
You can loop through the array and then loop through the keys of each object. Then increment the key of the countObject if it already exists or assign it zero.
This is dynamic. Even if one of the object has an extra key, it will count them. This doesn't expect all the items of array to have the same keys.
var array = [
{"taco":"","burrito":"","scone":"","beans":"true"},
{"taco":"true","burrito":"","scone":"true","beans":""},
{"taco":"true","burrito":"","scone":"","beans":""},
{"taco":"true","burrito":"","scone":"","beans":"true"}
]
var countObject = {};
array.forEach(item => {
Object.keys(item).forEach(key => {
if (item[key] === "true")
countObject[key] = countObject[key] + 1 || 1
else
countObject[key] = countObject[key] || 0
})
})
console.log(countObject); // get the key and count pair
console.log(Object.values(countObject)); // get the counts in an array

How to get the highest key and value from object

I'm trying to get the highest key and value from an object, how can I return the desired result?
Here's my object:
categories = {
'personal' : 4,
'swag' : 3,
'mingle' : 2,
'attention' : 1
};
Desired functionality:
returnMax(categories) // {personal : 4}
Here is how I would do it: http://jsfiddle.net/nwj7sad1/5/
categories = {
'personal' : 4,
'swag' : 3,
'mingle' : 2,
'attention' : 1
};
console.log(MaxCat(categories));
function MaxCat(obj){
var highest = 0;
var arr = [];
for (var prop in obj) {
if( obj.hasOwnProperty( prop ) ) {
if(obj[prop] > highest ){
arr = [];
highest = obj[prop];
arr[prop] = highest;
}
}
}
return arr;
}
For these types of things I like to write my own algorythms. Here is one I quickly wrote up:
function highest(o){
var h = undefined;
for(var key in o){
var current = o[key];
if(h === undefined || current > h){
h = current;
}
}
return h;
}
JSFiddle

How can I find which index in an array contains an object whose value for a specific key is x? [duplicate]

I would like to find index in array. Positions in array are objects, and I want to filter on their properties. I know which keys I want to filter and their values. Problem is to get index of array which meets the criteria.
For now I made code to filter data and gives me back object data, but not index of array.
var data = [
{
"text":"one","siteid":"1","chid":"default","userid":"8","time":1374156747
},
{
"text":"two","siteid":"1","chid":"default","userid":"7","time":1374156735
}
];
var filterparams = {userid:'7', chid: 'default'};
function getIndexOfArray(thelist, props){
var pnames = _.keys(props)
return _.find(thelist, function(obj){
return _.all(pnames, function(pname){return obj[pname] == props[pname]})
})};
var check = getIndexOfArray(data, filterparams ); // Want to get '2', not key => val
Using Lo-Dash in place of underscore you can do it pretty easily with _.findIndex().
var index = _.findIndex(array, { userid: '7', chid: 'default' })
here is thefiddle hope it helps you
for(var intIndex=0;intIndex < data.length; intIndex++){
eachobj = data[intIndex];
var flag = true;
for (var k in filterparams) {
if (eachobj.hasOwnProperty(k)) {
if(eachobj[k].toString() != filterparams[k].toString()){
flag = false;
}
}
}
if(flag){
alert(intIndex);
}
}
I'm not sure, but I think that this is what you need:
var data = [{
"text":"one","siteid":"1","chid":"default","userid":"8","time":1374156747
}, {
"text":"two","siteid":"1","chid":"default","userid":"7","time":1374156735
}];
var filterparams = {userid:'7', chid: 'default'};
var index = data.indexOf( _.findWhere( data, filterparams ) );
I don't think you need underscore for that just regular ole js - hope this is what you are looking for
var data = [
{
"text":"one","siteid":"1","chid":"default","userid":"8","time":1374156747
},
{
"text":"two","siteid":"1","chid":"default","userid":"7","time":1374156735
}
];
var userid = "userid"
var filterparams = {userid:'7', chid: 'default'};
var index;
for (i=0; i < data.length; i++) {
for (prop in data[i]) {
if ((prop === userid) && (data[i]['userid'] === filterparams.userid)) {
index = i
}
}
}
alert(index);

remove duplicated value from array and replace it with the latest value in javascript

I have an array in JavaScript. The user enters string and the data placed in this array in the form of value and name.
if(!_.isUndefined(args[1]) && !_.isUndefined(args[2])) {
if(args[1].length !== 0 && args[2].length !== 0) {
var dataObj = {
name : args[1],
value : args[2]
};
formateArray.push({name: dataObj.name, value:dataObj.value});
How can I remove duplicated value from array and replace it with the latest value the user enters?
So when the user enters: value_1 100, value_2 200, value_1 500
I expect to see: value_1 500, value_2 200 (replace the duplicates with new data)
You can iterate your array replace the value if the name already exists.
function push(array, newVal) {
var found = false;
for (var i = 0; i < array.length && !found; i++) {
if (array[i].name === newVal.name) {
array[i].value = newVal.value;
found = true;
}
}
if (!found) {
array.push(newVal);
}
}
function printNameValue(array) {
var out = '';
for (var i = 0; i < array.length; i++) {
out += array[i].name + ' ' + array[i].value + ', ';
}
return out;
}
var myArray = [];
push(myArray, {
name: 'value_1',
value: 100
});
push(myArray, {
name: 'value_2',
value: 200
});
push(myArray, {
name: 'value_1',
value: 500
});
alert(printNameValue(myArray));
Since your values can be associated with meaningful keys, perhaps you should use an object map rather than an array to store your values. Avoiding duplicates now becomes trivial since you cannot have duplicate keys.
var valuesMap = {};
//setting value
valuesMap.value_1 = 100;
//setting another value
valuesMap.value_2 = 200;
//replacing it
valuesMap.value_1 = 500;
Otherwise it's still quite simple, but less efficient:
function add(arr, obj) {
var key = obj.name, i, len;
for (i = 0, len = arr.length; i < len; i++) {
if (arr[i].name === key) {
arr[i] = obj;
return;
}
}
arr.push(obj);
}
var values = [];
add(values, { name: 'test', value: 1 });
add(values, { name: 'test', value: 2 });
values.length; //1
Instead of the array object, i suggest you to use an object that will act like a hashtable. You can define on this way var formateArray = {};
When you want to add or edit the data, instead of using push, you can do it like this:
formateArray[dataObj.name] = {name: dataObj.name, value:dataObj.value};
If the key does not exist dataObj.name, it will be added. It the key exist, the value would set with the new value.
If you want the size of you array, you get it this way Object.keys(formateArray).length
If you want to loop on your data, you can do it this way:
for (var k in formateArray) {
// use hasOwnProperty to filter out keys from the Object.prototype
if (formateArray.hasOwnProperty(k)) {
alert('key is: ' + k + ', value is: ' + formateArray[k].value);
}
}
Here is a jsfiddle that illustrate this.

Categories

Resources