I have a collection of array-like objects like this :
a = [[1,2],[3,4],[5,6],[7,8]]
And I would like to sum the columns (if u think of this as a 4x2 array) such that:
col1_sum = 16
col2_sum = 20
What is the best way of doing this is JS?
I tried using underscore's _.reduce function like so:
var col1_sum =_.reduce(a, function(memo,obj){ return memo + parseFloat(obj[0]);},0)
but I get an "undefined" error
any ideas? thank you.
You could always kick it old school. It's not pretty, but it works.
col1_sum = 0;
col2_sum = 0;
for (var i = 0; i < a.length; ++i) {
col1_sum += a[i][0];
col2_sum += a[i][1];
}
My other thought was to use jQuery's each function, but I guess you're not looking for a jQuery solution?
EDIT - Who needs jQuery.each? Just use JavaScript's Array.forEach:
var col1_sum = 0;
var col2_sum = 0;
a = [[1,2],[3,4],[5,6],[7,8]];
a.forEach(function(element, index, array) { col1_sum += element[0]; col2_sum += element[1]; });
alert(col1_sum);
alert(col2_sum);
I made a simple jsfiddle from your underscore reduce code, and it seems to be working fine: http://jsfiddle.net/PdL5P/
var a = [[1,2],[3,4],[5,6],[7,8]]
var col1_sum = _.reduce(a, function(memo,obj){ return memo + parseFloat(obj[0]); }, 0 );
$("#sum").html(col1_sum)
Are you sure that "a" is defined at that point of your code?
You can also kick it new school:
var sumColumnJS = function sumColumnJS(array, col) {
var sum = 0;
array.forEach(function (value, index, array) {
sum += value[col];
});
return sum;
};
or use the _.each array iterator:
sumColumn_ = function sumColumn_(array, col) {
var sum = 0;
_.each(a, function (item) {
sum += item[col];
});
return sum;
};
Working demo: http://jsfiddle.net/HTqvf/
Simple iteration, as in any traditional language
var col1_sum = 0, col2_sum = 0, row;
for (row in a)
{
col1_sum += a[row][0];
cos2_sum += a[row][1];
}
I would do this.
a = [[1,2],[3,4],[5,6],[7,8]]
col1_sum = _.sum(_.map(a,0))
col2_sum = _.sum(_.map(a,1))
Related
I want to apply a function to each of the values at all levels of the array:
arr = [[1,2,3],[1,2,3],[[1,2],[1,2]],1,2,3]
for example, multiply all the values by 3, and map it in the same format as before so I get:
arr = [[3,6,9],[3,6,9],[[3,6],[3,6]],3,6,9]
What would be the best way to go about this?
I tried to use a recursive function:
function mapall(array){
array.map(function(obj){
if (Array.isArray(obj)===true) { return mapall(obj) }
else{ return obj*3 }
})
};
but when I run it I just get undefined, so I must be doing something not quite right??
Any ideas??
Thanks
Everything was working, but you forgot to return from array.map. Here's a cleaner version of your code:
var arr = [[1,2,3],[1,2,3],[[1,2],[1,2]],1,2,3];
function mapAll(array){
return array.map(function(item){
return Array.isArray(item) ? mapAll(item) : item * 3;
});
}
alert(JSON.stringify(mapAll(arr)));
Version with callback function where you can do with array elements what you want (el * 2 or something else)
var arr = [[1,2,3],[1,2,3],[[1,2],[1,2]],1,2,3];
function mapAll(array, cb) {
for (var i = 0, len = array.length; i < len; i++) {
if (Array.isArray(array[i])) {
mapAll(array[i], cb);
} else {
array[i] = cb(array[i]);
}
}
return array;
};
var res = mapAll(arr, function (el) {
return el * 3;
});
console.log(JSON.stringify(res));
For example:
input: var arr = ['a','b','c','a-5','c-2'];
output: var result = {'a':6,'b':1,'c':'3'} ;
My solution is:
function countSameItem(arr) {
var counter = {};
for (var i = 0; i < arr.length; i++) {
var item = arr[i].split('-');
if (item.length === 1) {
counter[item] = (counter[item] + 1) || 1;
} else {
counter[item[0]] = (counter[item[0]] + parseInt(item[1]) || parseInt(item[1]));
}
}
return counter;
}
But I want to thought a more consise solution using the lodash
You can do it concisely without lodash:
var result = ['a','b','c','a-5','c-2'].reduce(function(o, s) {
var a = s.split('-').concat(1);
return o[a[0]] = (o[a[0]] || 0) + +a[1], o;
}, Object.create(null));
with lodash you would use the _.reduce function in a similar manner to the way Oriol uses the native reduce function
function countSameItem(arr) {
return _.reduce( arr, function(counter, n, i) {
var narr=n.split('-');
counter[narr[0]] = (counter[narr[0]] || 0) + (1*narr[1] || 1);
return counter;
}, {});
}
counter is the accumulator and what is eventually returned from the function.
n is each element
i is the index of each element.
for each element in the input array counter gets the value returned by the last element that was ran. The third argument in _.reduce gives the initial value of counter.
Using the native implementation is probably better unless you are using lodash for other features and want consistency in the code.
The lodash version of reduce does have the benefit of working on objects as well as arrays but this can be done natively as well by using Object.keys(arr).reduce
I have the following object:
{"speed":299,"equipment":49,"teleabb":49,"additional":50,"optional":"299"}
I want to sum all this values and print It out. How can I sum the properties values? :)
Iterate over the object properties using for(var in)
Use parseInt since some of the integers are in string form
var obj = {"speed":299,"equipment":49,"teleabb":49,"additional":50,"optional":"299"};
var sum = 0;
for(var key in obj){
sum += parseInt(obj[key]);
}
document.write(sum);
Here's a way of doing it using ES5's Object.keys and reduce:
var obj = {"speed":299,"equipment":49,"teleabb":49,"additional":50,"optional":"299"};
var sum = Object.keys(obj).reduce(function(prev, current, index) {
return prev + (+obj[current]);
}, 0);
console.log(sum); // 746
jsFiddle
My for-less version:
var obj = {"speed":299,"equipment":49,"teleabb":49,"additional":50,"optional":"299"};
function sumProperties(obj) {
return Object.getOwnPropertyNames(obj)
.map(function(item){ return +obj[item];})
.reduce(function(acc,item) { return acc + item; });
}
document.write(sumProperties(obj));
Given
var obj = {"speed":299,"equipment":49,"teleabb":49,"additional":50,"optional": 299}
you can do it very easily with the lodash library:
var result = _.sum(obj);
If some of your values aren't numbers, you need to map them to numbers first:
var result = _.sum(_.map(obj, function(n){
return +n;
//or parseInt(n) or parseInt(n,10)
}));
http://plnkr.co/edit/UQs1aTCJ8qe1kG15G4x7?p=preview
You can do it this way:
var sum_object = {"speed":299,"equipment":49,"teleabb":49,"additional":50,"optional":"299"};
var sum = 0;
for( var index in sum_object ){
sum += parseInt(sum_object[index]);
console.log("Val: ",sum_object[index], sum);
};
console.log(sum);
JSFiddle: http://jsfiddle.net/abvuh5m0/
var obj = {"speed":299,"equipment":49,"teleabb":49,"additional":50,"optional":"299"};
function sum(obj){
var sum = 0;
for(var key in obj){
if (obj. hasOwnProperty(key)) {
sum += parseInt(obj[key]) || 0;
}
}
return sum
}
console.log(sum(obj));
parseInt(obj[key]) || 0; is important id the value is not a number
Using Lodash:
var obj = {"speed":299,"equipment":49,"teleabb":49,"additional":50,"optional":"299"};
var val = _.sumBy(_.values(obj), function(v) {
return parseInt(v)
});
Example: https://codepen.io/dieterich/pen/dyymoxM?editors=0012
var sum = 0;
for(var key in objects) {
sum += parseInt(objects[key]);
}
console.log(sum);
Ok, this might be easy for some genius out there but I'm struggling...
This is for a project I'm working on with a slider, I want an array the slider can use for snap points/increments... I'm probably going about this in a mental way but its all good practice! Please help.
var frootVals = [1,2,3,4,5];
var frootInc = [];
for (i=0; i<=frootVals.length; i++) {
if (i == 0){
frootInc.push(frootVals[i]);
}
else{
frootInc.push(frootInc[i-1] += frootVals[i])
}
};
What I'm trying to do is create the new array so that its values are totals of the array elements in frootVals.
The result I'm looking for would be this:
fruitInc = [1,3,6,10,15]
For a different take, I like the functional approach:
var frootVals = [1,2,3,4,5];
var frootInc = [];
var acc = 0;
frootVals.forEach(function(i) {
acc = acc + i;
frootInc.push(acc);
});
var frootVals = [1,2,3,4,5]
, frootInc = [];
// while i < length, <= will give us NaN for last iteration
for ( i = 0; i < frootVals.length; i++) {
if (i == 0) {
frootInc.push(frootVals[i]);
} else {
// rather than frootIne[ i-1 ] += ,
// we will just add both integers and push the value
frootInc.push( frootInc[ i-1 ] + frootVals[ i ] )
}
};
There were a few things wrong with your code check out the commenting in my code example. Hope it helps,
This will do:
var frootVals = [1,2,3,4,5];
var frootInc = [];
for (i=0; i < frootVals.length; i++) { // inferior to the length of the array to avoid iterating 6 times
if (i == 0) {
frootInc.push(frootVals[i]);
}
else {
frootInc.push(frootInc[i-1] + frootVals[i]) // we add the value, we don't reassign values
}
};
alert(JSON.stringify(frootInc));
jsfiddle here: http://jsfiddle.net/f01yceo4/
change your code to:
var frootVals = [1,2,3,4,5];
var frootInc = [frootvals[0]]; //array with first item of 'frootVals' array
for (i=1; i<frootVals.length; i++) {
frootInc.push(frootInc[i-1] + frootVals[i]); //remove '='
}
Here's a very simple pure functional approach (no vars, side-effects, or closures needed):
[1,2,3,4,5].map(function(a){return this[0]+=a;}, [0]);
// == [1, 3, 6, 10, 15]
if you name and un-sandwich the function, you can use it over and over again, unlike a hard-coded var name, property name, or for-loop...
I have an array with anonymous elements. Elements are added to the array via php, like so:
$playlist = array();
while (databaseloop) {
$playlist[] = $a_title;
$playlist[] = $a_length;
}
echo json_encode(array('playlist'=>$playlist));
So the array becomes:
["Hello.mp3", "00:00:14", "Byebye.mp3", "00:00:30", "Whatsup.mp3", "00:00:07", "Goodnight.mp3", "00:00:19"] and so on
Then I retrieve this array in jquery with ajax post. All that works fine.
Now, I'm looking for a way to treat/output all array elements as pairs in javascript/jquery. "do something" for each second element. Like this:
foreach (two_elements_in_array) {
// output track name
// output track time
// output some divider
}
How can this be done?
Well, maybe this is the most basic solution:
for (var i = 0; i < arr.length; i += 2) {
var title = arr[i];
var len = arr[i+1];
}
However, I would recommend you to arrange $playlist as follows:
while (databaseloop) {
$playlist[] = array(
"title" => $a_title,
"length" => $a_length
);
}
Then it will be easy to iterate the elements simply with:
for (var i = 0; i < arr.length; i++) {
var title = arr[i]['title'];
var len = arr[i]['length'];
}
You could split the array into an array of two-element arrays.
var arr = ["Hello.mp3", "00:00:14", "Byebye.mp3", "00:00:30", "Whatsup.mp3", "00:00:07", "Goodnight.mp3", "00:00:19"];
arr.map(function(elem,i,arr){return [elem, (i+1<arr.length) ? arr[i+1] : null];})
.filter(function(elem,i){return !(i%2);});
Using Array.prototype.reduce():
let pairs = playlist.reduce((list, _, index, source) => {
if (index % 2 === 0) {
list.push(source.slice(index, index + 2));
}
return list;
}, []);
This gives you a 2-dimensional array pairs to work with.
A simple for loop with an increment of two. You might want to make sure that your array length is long enough for i+1, in case the length isn't divisible by 2!
for (i = 0; i+1 < array.length; i+=2) {
name = array[i];
length = array[i+1];
}
var arr = ["Hello.mp3", "00:00:14", "Byebye.mp3", "00:00:30", "Whatsup.mp3", "00:00:07", "Goodnight.mp3", "00:00:19"];
var group = [];
for (var x = 0; x < arr.length; x += 2) {
var track = arr[x],
length = arr[x + 1];
group.push({
track: track,
length: length
})
}
I would suggest that you optimize your code a little bit more so that it would make a bit more sense and be less error prone, if that's possible that is.
This is also a great way to be more object-oriented!
Like this (I'm using jQuery here) :
var array = [ {name: "Hello.mp3", time: "00:00:14"}, {name: "Byebye.mp3", time:"00:00:30"}, {name: "Whatsup.mp3", time: "00:00:07"}, {name: "Goodnight.mp3", time: "00:00:19"}];
Then you would be able to loop over it and produce a bit more clean looking code
array.forEach(function(data){
//edit the output here
console.log(data.name + " " + data.time );
});
as #VisioN said it would be easier if you use associative array or else you can have a separated array of labels while iterating on the client side
var d=["Hello.mp3", "00:00:14", "Byebye.mp3", "00:00:30", "Whatsup.mp3", "00:00:07", "Goodnight.mp3", "00:00:19"] ;
var e=["name","time"];
var c=0;
$.each(d,function(i,j){
if(c>=2)c=0;
console.log(e[c]+j);
c++;
});
http://jsfiddle.net/FmLYk/1/
Destructive, but clean:
while (arr.length) {
const Title = arr.shift();
const Length = arr.shift();
// Do work.
}
Not with foreach.
for (var i = 0; i < array.length; i += 2) {
var name = array[i];
var time = array[i + 1];
// do whatever
}