Javascript count keys in braces of function - javascript

I call a function like so:
update_insert('information',{
element_id: 1,
type: 'menu',
info: 'Hi how are ya?',
new_window: ''
});
The function is:
function update_insert(table,data){
alert(data.length);
}
I am trying to get the number of keys that I inserted into the function, and eventually get the names of the keys, dynamically with a loop. How can I achieve this?

Objects don't have the .length attribute like arrays do in JavaScript. You'll need to use a function to count the number of items in an object:
getObjectLength = function(obj) {
var size = 0, key;
for (key in obj) {
if (obj.hasOwnProperty(key))
size++;
}
return size;
}
EDIT:
And to get the keys from an object:
getObjectKeys = function(obj) {
var keys = [];
for (var key in obj) {
keys.push(key);
}
return keys;
}

You can get the keys with the following function (which is safe to use in older browsers)...
var getObjectKeys = function(obj) {
if (Object.keys && typeof Object.keys == "function") {
return Object.keys(obj);
}
var prop, keys = [];
for (prop in obj) {
if (obj.hasOwnProperty(prop)) {
keys.push(prop);
}
}
return keys;
}
jsFiddle.
Alternatively, use Object.keys() and use an equivalent [shim][2] for older browsers.
You can check the length property of the returned Array to determine the amount of keys.
If you want to dredge up all enumerable properties on the prototype chain, you can use...
var getObjectKeysIncludingInherited = function(obj) {
var keys = [],
i = 0;
for (keys[i++] in obj);
return keys;
}
jsFiddle.
Alternatively, you may really want to use the length property of an object to do it, but please don't. It's considered somewhat dangerous to augment native JavaScript objects, and it's kind of confusing (Objects don't have a length property but Arrays do) and it won't work in older browsers...
Object.defineProperty(Object.prototype, "length", {
get: function() {
return Object.keys(this).length;
}
});
jsFiddle.

Something like this, perhaps?
function update_insert(table,data){
var dataLength = 0, keys = [];
for(prop in data) {
if(data.hasOwnProperty(prop)) {
dataLength++;
keys.push(prop);
}
}
}
Arrays are actually objects which have a custom length property (and some other stuff :P) so not all objects have a length property.

var names = new Array();
for(name in data)
{
if(data.hasOwnProperty(name))
{
names.push(name);
}
}
names.length - will give you what you need.

var keys = [];
for(var k in data) {
if(Object.prototype.hasOwnProperty(data, k)) {
keys.push(data[k]);
}
}
k.length //size of keys

In case you are a jQuery fan or potential user:
var size = 0;
$.each(obj, function(key, value) {
alert('key = ' + key);
alert('value = ' + value);
size++;
});
alert(size);

Related

Get the format of the fields in a Typescript class [duplicate]

How can I loop through all members in a JavaScript object, including values that are objects?
For example, how could I loop through this (accessing the "your_name" and "your_message" for each)?
var validation_messages = {
"key_1": {
"your_name": "jimmy",
"your_msg": "hello world"
},
"key_2": {
"your_name": "billy",
"your_msg": "foo equals bar"
}
}
for (var key in validation_messages) {
// skip loop if the property is from prototype
if (!validation_messages.hasOwnProperty(key)) continue;
var obj = validation_messages[key];
for (var prop in obj) {
// skip loop if the property is from prototype
if (!obj.hasOwnProperty(prop)) continue;
// your code
alert(prop + " = " + obj[prop]);
}
}
Under ECMAScript 5, you can combine Object.keys() and Array.prototype.forEach():
var obj = {
first: "John",
last: "Doe"
};
//
// Visit non-inherited enumerable keys
//
Object.keys(obj).forEach(function(key) {
console.log(key, obj[key]);
});
In ES6/2015 you can loop through an object like this (using the arrow function):
Object.keys(myObj).forEach(key => {
console.log(key); // the name of the current key.
console.log(myObj[key]); // the value of the current key.
});
JS Bin
In ES7/2016 you can use Object.entries instead of Object.keys and loop through an object like this:
Object.entries(myObj).forEach(([key, val]) => {
console.log(key); // the name of the current key.
console.log(val); // the value of the current key.
});
The above would also work as a one-liner:
Object.entries(myObj).forEach(([key, val]) => console.log(key, val));
jsbin
In case you want to loop through nested objects as well, you can use a recursive function (ES6):
const loopNestedObj = obj => {
Object.keys(obj).forEach(key => {
if (obj[key] && typeof obj[key] === "object") loopNestedObj(obj[key]); // recurse.
else console.log(key, obj[key]); // or do something with key and val.
});
};
JS Bin
The same as function above, but with ES7 Object.entries() instead of Object.keys():
const loopNestedObj = obj => {
Object.entries(obj).forEach(([key, val]) => {
if (val && typeof val === "object") loopNestedObj(val); // recurse.
else console.log(key, val); // or do something with key and val.
});
};
Here we loop through nested objects change values and return a new object in one go using Object.entries() combined with Object.fromEntries() (ES10/2019):
const loopNestedObj = obj =>
Object.fromEntries(
Object.entries(obj).map(([key, val]) => {
if (val && typeof val === "object") [key, loopNestedObj(val)]; // recurse
else [key, updateMyVal(val)]; // or do something with key and val.
})
);
Another way of looping through objects is by using for ... in and for ... of. See vdegenne's nicely written answer.
The problem with this
for (var key in validation_messages) {
var obj = validation_messages[key];
for (var prop in obj) {
alert(prop + " = " + obj[prop]);
}
}
is that you’ll also loop through the primitive object's prototype.
With this one you will avoid it:
for (var key in validation_messages) {
if (validation_messages.hasOwnProperty(key)) {
var obj = validation_messages[key];
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
alert(prop + " = " + obj[prop]);
}
}
}
}
Using Underscore.js’s _.each:
_.each(validation_messages, function(value, key){
_.each(value, function(value, key){
console.log(value);
});
});
This answer is an aggregate of the solutions that were provided in this
post with some performance feedbacks. I think there is two
use cases and the OP didn't mention if he needs to access the keys in order use them
during the loop process.
I. The keys need to be accessed
✔ The of and Object.keys approach
let k;
for (k of Object.keys(obj)) {
/* k : key
* obj[k] : value
*/
}
✔ The in approach
let k;
for (k in obj) {
/* k : key
* obj[k] : value
*/
}
Use this one with caution, as it could print prototype'd properties of obj
✔ The ES7 approach
for (const [key, value] of Object.entries(obj)) {
}
However, at the time of the edit I wouldn't recommend the ES7 method, because JavaScript initializes a lot of variables internally to build this procedure (see the feedbacks for proof). Unless you are not developing a huge application which deserves optimization, then it is OK, but if optimization is your priority, you should think about it.
II. We just need to access each value
✔ The of and Object.values approach
let v;
for (v of Object.values(obj)) {
}
More feedbacks about the tests:
Caching Object.keys or Object.values performance is negligible
For instance,
const keys = Object.keys(obj);
let i;
for (i of keys) {
//
}
// same as
for (i of Object.keys(obj)) {
//
}
For Object.values case, using a native for loop with cached variables in Firefox seems to be a little faster than using a for...of loop. However, the difference is not that important and Chrome is running for...of faster than native for loop, so I would recommend to use for...of when dealing with Object.values in any cases (4th and 6th tests).
In Firefox, the for...in loop is really slow, so when we want to cache the key during the iteration it is better to use Object.keys. Plus Chrome is running both structure at equal speed (first and last tests).
You can check the tests here: https://jsperf.com/es7-and-misc-loops
If you use recursion you can return object properties of any depth-
function lookdeep(object){
var collection= [], index= 0, next, item;
for(item in object){
if(object.hasOwnProperty(item)){
next= object[item];
if(typeof next== 'object' && next!= null){
collection[index++]= item +
':{ '+ lookdeep(next).join(', ')+'}';
}
else collection[index++]= [item+':'+String(next)];
}
}
return collection;
}
//example
var O={
a:1, b:2, c:{
c1:3, c2:4, c3:{
t:true, f:false
}
},
d:11
};
var lookdeepSample= 'O={'+ lookdeep(O).join(',\n')+'}';
/* returned value: (String)
O={
a:1,
b:2,
c:{
c1:3, c2:4, c3:{
t:true, f:false
}
},
d:11
}
*/
for(var k in validation_messages) {
var o = validation_messages[k];
do_something_with(o.your_name);
do_something_else_with(o.your_msg);
}
An optimized and improved version of AgileJon's answer:
var key, obj, prop, owns = Object.prototype.hasOwnProperty;
for (key in validation_messages ) {
if (owns.call(validation_messages, key)) {
obj = validation_messages[key];
for (prop in obj ) {
// Using obj.hasOwnProperty might cause you headache if there is
// obj.hasOwnProperty = function(){return false;}
// but 'owns' will always work
if (owns.call(obj, prop)) {
console.log(prop, "=", obj[prop]);
}
}
}
}
p is the value
for (var key in p) {
alert(key + ' => ' + p[key]);
}
OR
Object.keys(p).forEach(key => { console.log(key, p[key]) })
In ES7 you can do:
for (const [key, value] of Object.entries(obj)) {
//
}
for(var key in validation_messages){
for(var subkey in validation_messages[key]){
//code here
//subkey being value, key being 'yourname' / 'yourmsg'
}
}
A few ways to do that...
1) A two-layer for...in loop...
for (let key in validation_messages) {
const vmKeys = validation_messages[key];
for (let vmKey in vmKeys) {
console.log(vmKey + vmKeys[vmKey]);
}
}
2) Using Object.key
Object.keys(validation_messages).forEach(key => {
const vmKeys = validation_messages[key];
Object.keys(vmKeys).forEach(key => {
console.log(vmKeys + vmKeys[key]);
});
});
3) Recursive function
const recursiveObj = obj => {
for(let key in obj){
if(!obj.hasOwnProperty(key)) continue;
if(typeof obj[key] !== 'object'){
console.log(key + obj[key]);
} else {
recursiveObj(obj[key]);
}
}
}
And call it like:
recursiveObj(validation_messages);
Another option:
var testObj = {test: true, test1: false};
for(let x of Object.keys(testObj)){
console.log(x);
}
There are so many ways to traverse an object. Please have a look at below examples.
var obj = {'name':'John Doe','email':'johndoe#example.com'}
Approach 1
var keys = Object.keys(obj)
for(var i= 0; i < keys.length;i++){
console.log(keys[i]+ ': ' + obj[keys[i]])
}
Approach 2
for(var key in obj){
console.log(key+': '+ obj[key])
}
Approach 3
Object.keys(obj).forEach(function (key) {
console.log(key+ ': ' + obj[key])
})
Here comes the improved and recursive version of AgileJon's solution (demo):
function loopThrough(obj){
for(var key in obj){
// skip loop if the property is from prototype
if(!obj.hasOwnProperty(key)) continue;
if(typeof obj[key] !== 'object'){
//your code
console.log(key+" = "+obj[key]);
} else {
loopThrough(obj[key]);
}
}
}
loopThrough(validation_messages);
This solution works for all kinds of different depths.
ECMAScript 2017, just finalized a month ago, introduces Object.values(). So now you can do this:
let v;
for (v of Object.values(validation_messages))
console.log(v.your_name); // jimmy billy
var validation_messages = {
"key_1": {
"your_name": "jimmy",
"your_msg": "hello world"
},
"key_2": {
"your_name": "billy",
"your_msg": "foo equals bar"
}
}
for (var i in validation_messages) {
console.log("i = \"" + i + "\"");
console.log("validation_messages[\"" + i + "\"] = ");
console.log(validation_messages[i]);
console.log("\n");
for (var j in validation_messages[i]) {
console.log("j = \"" + j + "\"");
console.log("validation_messages[\"" + i + "\"][\"" + j + "\"] = \"" + validation_messages[i][j] + "\"");
console.log("\n");
}
console.log('\n');
}
Outputs:
i = "key_1"
validation_messages["key_1"] =
{
your_name:"jimmy",
your_msg:"hello world"
}
j = "your_name"
validation_messages["key_1"]["your_name"] = "jimmy"
j = "your_msg"
validation_messages["key_1"]["your_msg"] = "hello world"
i = "key_2"
validation_messages["key_2"] =
{
your_name:"billy",
your_msg:"foo equals bar"
}
j = "your_name"
validation_messages["key_2"]["your_name"] = "billy"
j = "your_msg"
validation_messages["key_2"]["your_msg"] = "foo equals bar"
I think it's worth pointing out that jQuery sorts this out nicely with $.each().
See: .each()
Example:
$('.foo').each(function() {
console.log($(this));
});
$(this) being the single item inside the object. Swap $('.foo') to a variable if you don't want to use jQuery's selector engine.
I couldn't get the previous answere to do quite what I was after.
After playing around with the other replies here, I made this. It's hacky, but it works!
For this object:
var myObj = {
pageURL : "BLAH",
emailBox : {model:"emailAddress", selector:"#emailAddress"},
passwordBox: {model:"password" , selector:"#password"}
};
... this code:
// Get every value in the object into a separate array item ...
function buildArray(p_MainObj, p_Name) {
var variableList = [];
var thisVar = "";
var thisYes = false;
for (var key in p_MainObj) {
thisVar = p_Name + "." + key;
thisYes = false;
if (p_MainObj.hasOwnProperty(key)) {
var obj = p_MainObj[key];
for (var prop in obj) {
var myregex = /^[0-9]*$/;
if (myregex.exec(prop) != prop) {
thisYes = true;
variableList.push({item:thisVar + "." + prop,value:obj[prop]});
}
}
if ( ! thisYes )
variableList.push({item:thisVar,value:obj});
}
}
return variableList;
}
// Get the object items into a simple array ...
var objectItems = buildArray(myObj, "myObj");
// Now use them / test them etc... as you need to!
for (var x=0; x < objectItems.length; ++x) {
console.log(objectItems[x].item + " = " + objectItems[x].value);
}
... produces this in the console:
myObj.pageURL = BLAH
myObj.emailBox.model = emailAddress
myObj.emailBox.selector = #emailAddress
myObj.passwordBox.model = password
myObj.passwordBox.selector = #password
var obj = {
name: "SanD",
age: "27"
}
Object.keys(obj).forEach((key) => console.log(key,obj[key]));
To loop through the JavaScript Object we can use forEach and to optimize the code we can use the arrow function.
using lodash _.forEach:
_.forEach({ 'a': 1, 'b': 2 }, function(value, key) {
console.log(key, value);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
forEach2
(Found here):
var lunch = {
sandwich: 'ham',
age: 48,
};
lunch.forEach2(function (item, key) {
console.log(key);
console.log(item);
});
Code:
if (!Object.prototype.forEach2) {
Object.defineProperty(Object.prototype, 'forEach2', {
value: function (callback, thisArg) {
if (this == null) {
throw new TypeError('Not an object');
}
thisArg = thisArg || window;
for (var key in this) {
if (this.hasOwnProperty(key)) {
callback.call(thisArg, this[key], key, this);
}
}
}
});
}
Using ES8 Object.entries() should be a more compact way to achieve this.
Object.entries(validation_messages).map(([key,object]) => {
alert(`Looping through key : ${key}`);
Object.entries(object).map(([token, value]) => {
alert(`${token} : ${value}`);
});
});
The solution that works for me is the following:
_private.convertParams = function(params){
var params = [];
Object.keys(values).forEach(function(key) {
params.push({"id":key, "option":"Igual", "value":params[key].id})
});
return params;
}
Exotic one - deep traverse
JSON.stringify(validation_messages,(field,value)=>{
if(!field) return value;
// ... your code
return value;
})
In this solution we use replacer which allows to deep traverse the whole object and nested objects - on each level you will get all fields and values. If you need to get the full path to each field, look here.
var validation_messages = {
"key_1": {
"your_name": "jimmy",
"your_msg": "hello world"
},
"key_2": {
"your_name": "billy",
"your_msg": "foo equals bar",
"deep": {
"color": "red",
"size": "10px"
}
}
}
JSON.stringify(validation_messages,(field,value)=>{
if(!field) return value;
console.log(`key: ${field.padEnd(11)} - value: ${value}`);
return value;
})
In 2020 you want immutable and universal functions
This walks through your multidimensional object composed of sub-objects, arrays and string and apply a custom function:
export const iterate = (object, func) => {
const entries = Object.entries(object).map(([key, value]) =>
Array.isArray(value)
? [key, value.map(e => iterate(e, func))]
: typeof value === 'object'
? [key, iterate(value, func)]
: [key, func(value)]
);
return Object.fromEntries(entries);
};
Usage:
const r = iterate(data, e=>'converted_'+e);
console.log(r);
In my case (on the basis of the preceding) it is possible for any number of levels.
var myObj = {
rrr: undefined,
pageURL : "BLAH",
emailBox : {model:"emailAddress", selector:"#emailAddress"},
passwordBox: {model:"password" , selector:"#password"},
proba: {odin:{dva:"rr",trr:"tyuuu"}, od:{ff:5,ppa:{ooo:{lll:'lll'}},tyt:'12345'}}
};
function lookdeep(obj,p_Name,gg){
var A=[], tem, wrem=[], dd=gg?wrem:A;
for(var p in obj){
var y1=gg?'':p_Name, y1=y1 + '.' + p;
if(obj.hasOwnProperty(p)){
var tem=obj[p];
if(tem && typeof tem=='object'){
a1=arguments.callee(tem,p_Name,true);
if(a1 && typeof a1=='object'){for(i in a1){dd.push(y1 + a1[i])};}
}
else{
dd.push(y1 + ':' + String(tem));
}
}
};
return dd
};
var s=lookdeep(myObj,'myObj',false);
for (var x=0; x < s.length; ++x) {
console.log(s[x]+'\n');}
Result:
["myObj.rrr:undefined",
"myObj.pageURL:BLAH",
"myObj.emailBox.model:emailAddress",
"myObj.emailBox.selector:#emailAddress",
"myObj.passwordBox.model:password",
"myObj.passwordBox.selector:#password",
"myObj.proba.odin.dva:rr",
"myObj.proba.odin.trr:tyuuu",
"myObj.proba.od.ff:5",
"myObj.proba.od.ppa.ooo.lll:lll",
"myObj.proba.od.tyt:12345"]

jQuery $.each with sorted object keys [duplicate]

Let's say I have a Javascript associative array (a.k.a. hash, a.k.a. dictionary):
var a = new Array();
a['b'] = 1;
a['z'] = 1;
a['a'] = 1;
How can I iterate over the keys in sorted order? If it helps simplify things, I don't even need the values (they're all just the number 1).
You can use the Object.keys built-in method:
var sorted_keys = Object.keys(a).sort()
(Note: this does not work in very old browsers not supporting EcmaScript5, notably IE6, 7 and 8. For detailed up-to-date statistics, see this table)
You cannot iterate over them directly, but you can find all the keys and then just sort them.
var a = new Array();
a['b'] = 1;
a['z'] = 1;
a['a'] = 1;
function keys(obj)
{
var keys = [];
for(var key in obj)
{
if(obj.hasOwnProperty(key))
{
keys.push(key);
}
}
return keys;
}
keys(a).sort(); // ["a", "b", "z"]
However there is no need to make the variable 'a' an array. You are really just using it as an object and should create it like this:
var a = {};
a["key"] = "value";
you could even prototype it onto object:
Object.prototype.iterateSorted = function(worker)
{
var keys = [];
for (var key in this)
{
if (this.hasOwnProperty(key))
keys.push(key);
}
keys.sort();
for (var i = 0; i < keys.length; i++)
{
worker(this[ keys[i] ]);
}
}
and the usage:
var myObj = { a:1, b:2 };
myObj.iterateSorted(function(value)
{
alert(value);
}
I agree with Swingley's answer, and I think it is an important point a lot of these more elaborate solutions are missing. If you are only concerned with the keys in the associative array and all the values are '1', then simply store the 'keys' as values in an array.
Instead of:
var a = { b:1, z:1, a:1 };
// relatively elaborate code to retrieve the keys and sort them
Use:
var a = [ 'b', 'z', 'a' ];
alert(a.sort());
The one drawback to this is that you can not determine whether a specific key is set as easily. See this answer to javascript function inArray for an answer to that problem. One issue with the solution presented is that a.hasValue('key') is going to be slightly slower than a['key']. That may or may not matter in your code.
There's no concise way to directly manipulate the "keys" of a Javascript object. It's not really designed for that. Do you have the freedom to put your data in something better than a regular object (or an Array, as your sample code suggests)?
If so, and if your question could be rephrased as "What dictionary-like object should I use if I want to iterate over the keys in sorted order?" then you might develop an object like this:
var a = {
keys : new Array(),
hash : new Object(),
set : function(key, value) {
if (typeof(this.hash[key]) == "undefined") { this.keys.push(key); }
this.hash[key] = value;
},
get : function(key) {
return this.hash[key];
},
getSortedKeys : function() {
this.keys.sort();
return this.keys;
}
};
// sample use
a.set('b',1);
a.set('z',1);
a.set('a',1);
var sortedKeys = a.getSortedKeys();
for (var i in sortedKeys) { print(sortedKeys[i]); }
If you have no control over the fact that the data is in a regular object, this utility would convert the regular object to your fully-functional dictionary:
a.importObject = function(object) {
for (var i in object) { this.set(i, object); }
};
This was a object definition (instead of a reusable constructor function) for simplicity; edit at will.
Get the keys in the first for loop, sort it, use the sorted result in the 2nd for loop.
var a = new Array();
a['b'] = 1;
a['z'] = 1;
a['a'] = 1;
var b = [];
for (k in a) b.push(k);
b.sort();
for (var i = 0; i < b.length; ++i) alert(b[i]);
You can use the keys function from the underscore.js library to get the keys, then the sort() array method to sort them:
var sortedKeys = _.keys(dict).sort();
The keys function in the underscore's source code:
// Retrieve the names of an object's properties.
// Delegates to **ECMAScript 5**'s native `Object.keys`
_.keys = nativeKeys || function(obj) {
if (obj !== Object(obj)) throw new TypeError('Invalid object');
var keys = [];
for (var key in obj) if (_.has(obj, key)) keys.push(key);
return keys;
};
// Shortcut function for checking if an object has a given property directly
// on itself (in other words, not on a prototype).
_.has = function(obj, key) {
return hasOwnProperty.call(obj, key);
};
<script type="text/javascript">
var a = {
b:1,
z:1,
a:1
}; // your JS Object
var keys = [];
for (key in a) {
keys.push(key);
}
keys.sort();
var i = 0;
var keyslen = keys.length;
var str = '';
//SORTED KEY ITERATION
while (i < keyslen) {
str += keys[i] + '=>' + a[keys[i]] + '\n';
++i;
}
alert(str);
/*RESULT:
a=>1
b=>1
z=>1
*/
</script>
var a = new Array();
a['b'] = 1;
a['z'] = 1;
a['a'] = 1;
var keys=Object.keys(a).sort();
for(var i=0,key=keys[0];i<keys.length;key=keys[++i]){
document.write(key+' : '+a[key]+'<br>');
}
I really like #luke-schafer's prototype idea, but also hear what he is saying about the issues with prototypes. What about using a simple function?
function sortKeysAndDo( obj, worker ) {
var keys = Object.keys(obj);
keys.sort();
for (var i = 0; i < keys.length; i++) {
worker(keys[i], obj[keys[i]]);
}
}
function show( key, value ) {
document.write( key + ' : ' + value +'<br>' );
}
var a = new Array();
a['b'] = 1;
a['z'] = 1;
a['a'] = 1;
sortKeysAndDo( a, show);
var my_object = { 'c': 3, 'a': 1, 'b': 2 };
sortKeysAndDo( my_object, show);
This seems to eliminate the issues with prototypes and still provide a sorted iterator for objects. I am not really a JavaScript guru, though, so I'd love to know if this solution has hidden flaws I missed.

Merge Objects in a JavaScript Array to object

I am trying to create a single JavaScript object from an array of objects.
Some values in the object remain the same, while the numerical or float values need to be summed up to form the new single object.
How can this be achieved?
[{
'visit_date': '2013-02-02',
'house_number': '22',
'price': 12.98,
'count_value': 21.554,
'variance': -23.434343434
},
{
'visit_date': '2013-02-02',
'house_number': '22',
'price': 34.78,
'count_value': 1.34,
'variance': -23.434343434
},
{
'visit_date': '2013-02-02',
'house_number': '22',
'price': 61.41,
'count_value':1.94,
'variance': -12.977677874
}]
You can use the reduce function to achieve it
var result = a.reduce(function (acc, c) {
acc.visit_date = c.visit_date;
acc.house_number = c.house_number;
acc.price += c.price;
acc.count_value += c.count_value;
acc.variance += c.variance;
return acc;
}, {
'visit_date': '',
'house_number': '',
'price': 0,
'count_value': 0,
'variance': 0
});
The result will be
{
visit_date: "2013-02-02",
house_number: "22",
price: 109.17,
count_value: 24.834,
variance: -59.846364742
}
Loop through the array, use a for-in loop on each object, and for entries where typeof value === "number", sum them up. Presumably do something useful when they aren't numbers, but you haven't said what. :-)
Sorry, missed the jQuery tag. It can be shorter with jQuery's each:
var dest = {};
$.each(source, function(index, entry) {
$.each(entry, function(key, value) {
if (typeof value === "number") {
dest[key] = key in dest ? dest[key] + value : value;
}
else {
// do something useful with non-numbers
}
});
});
each will loop through the array elements if you give it an array, or through the properties of an object if you give it a non-array object. So in the above, the outer each loops through your array, and the inner each loops through each object's properties.
The in operator on this line:
dest[key] = key in dest ? dest[key] + value : value;
...tells us whether dest already has a key with that name: If so, we add the value to it. If not, we create a new property for that key using the value.
Original non-jQuery:
Roughly:
var dest = {};
var entry;
var index;
var key;
var value;
for (index = 0; index < source.length; ++index) {
entry = source[index];
for (key in entry) {
value = entry[key];
if (typeof value === "number") {
dest[key] = key in dest ? dest[key] + value : value;
}
else {
// do something useful with non-numbers
}
}
}
Something like this perhaps? http://jsfiddle.net/tQLy5/1/
function aToObject(a) {
var o = {}, l = a.length;
while (l--) {
for (key in a[l]) {
if (o.hasOwnProperty(key) && typeof (o[key]) === 'number') {
o[key] += a[l][key];
} else {
o[key] = a[l][key];
}
}
}
return o;
}
Just iterate over the whole array and then over the properties of the objects in array. If the property is number you add them together, otherwise you just assign the property to the new object.

How to reduce a list of multiple items to a key value pair object in Javascript?

I have an array of states:
['CO','CA','CO','AL', ... ,'NV']
and I'd like to reduce to:
{ 'CO': 9, 'CA':17, 'AL':1, etc}
The value is the number of times each state occurs in the array.
what's the most efficient way to do this?
function compress2dict( raw_arr )
{
var ret={};
for(var i=0;i<raw_arr.length;i++)
{
var item=raw_arr[i];
ret[item]|=0;
ret[item]++;
}
return ret;
}
a = ['CO','BO','CO','CC','CC','CO','CC']
b = compress2dict(a)
b
{'BO':1, 'CC':3, 'CO':3}
You may be interested in array_count_values from PHPJS. Since the PHP array_count_values function does exactly what you want, it stands to reason that the JavaScript port of that function fits.
I expect you just iterate over the array, assign the member values to object property names and the number of occurences as the value:
function toObj(arr) {
var item, obj = {};
for (var i=0, iLen=arr.length; i<iLen; i++) {
item = arr[i];
obj[item]? ++obj[item] : (obj[item] = 1);
}
return obj;
}
Or if you like while loops (sometimes they're faster, sometimes not):
function toObj(arr) {
var item, obj = {}, i = arr.length;
while (i) {
item = arr[--i];
obj[item]? ++obj[item] : (obj[item] = 1);
}
return obj;
}

Hash keys / values as array [duplicate]

This question already has answers here:
How can I find the keys of an object?
(10 answers)
Closed 8 years ago.
I cannot find the JavaScript equivalent of PHP array_keys() / array_values().
For people unfamiliar with PHP given the following JavaScript hash:
var myHash = {"apples": 3, "oranges": 4, "bananas": 42}
How can I get an array of keys, i.e.,
["apples", "oranges", "bananas"]
The same question with the values, i.e.,
[3, 4, 42]
jQuery can be used.
In ES5 supported (or shimmed) browsers...
var keys = Object.keys(myHash);
var values = keys.map(function(v) { return myHash[v]; });
Shims from MDN...
Object.keys
Array.prototype.map
var a = {"apples": 3, "oranges": 4, "bananas": 42};
var array_keys = new Array();
var array_values = new Array();
for (var key in a) {
array_keys.push(key);
array_values.push(a[key]);
}
alert(array_keys);
alert(array_values);
The second answer (at the time of writing) gives:
var values = keys.map(function(v) { return myHash[v]; });
But I prefer using jQuery's own $.map:
var values = $.map(myHash, function(v) { return v; });
Since jQuery takes care of cross-browser compatibility. Plus it's shorter :)
At any rate, I always try to be as functional as possible. One-liners are nicers than loops.
Look at the _.keys() and _.values() functions in either Lodash or Underscore.js:
Underscore.js _.keys
Underscore.js _.values
Lodash _.keys
Lodash _.values
function getKeys(obj){
var keys = [];
for (key in obj) {
if (obj.hasOwnProperty(key)) { keys[keys.length] = key; }
}
return keys;
}
I don't know if it helps, but the "foreach" goes through all the keys:
for (var key in obj1) {...}
Here are implementations from phpjs.org:
array_values
array_keys
This is not my code. I'm just pointing you to a useful resource.
Use:
var myHash = {"apples": 3, "oranges": 4, "bananas": 42}
vals=(function(e){a=[];for (var i in e) a.push(e[i]); return a;})(myHash).join(',')
keys=(function(e){a=[];for (var i in e) a.push( i ); return a;})(myHash).join(',')
console.log(vals,keys)
Basically:
array=(function(e){a=[];for (var i in e) a.push(e[i]); return a;})(HASHHERE)
Here is a good example of array_keys from PHP.js library:
function array_keys (input, search_value, argStrict) {
// Return just the keys from the input array, optionally only for the specified search_value
var search = typeof search_value !== 'undefined',
tmp_arr = [],
strict = !!argStrict,
include = true,
key = '';
for (key in input) {
if (input.hasOwnProperty(key)) {
include = true;
if (search) {
if (strict && input[key] !== search_value) {
include = false;
}
else if (input[key] != search_value) {
include = false;
}
}
if (include) {
tmp_arr[tmp_arr.length] = key;
}
}
}
return tmp_arr;
}
The same goes for array_values (from the same PHP.js library):
function array_values (input) {
// Return just the values from the input array
var tmp_arr = [],
key = '';
for (key in input) {
tmp_arr[tmp_arr.length] = input[key];
}
return tmp_arr;
}

Categories