Javascript : How group and sum values from multidimensional array - javascript

I have an array like this:
I would like to group and get the sum of each repetition like this:
AGE270: 9
AGE203: 5
AGE208: 9
...
AGEXXX: n

Simple solution using Array.prototype.reduce function:
// Replace arr with your actual array!
var arr = [
{ AGENDADOR: 'AGE270', TOTAL : 6},
{ AGENDADOR: 'AGE270', TOTAL : 3},
{ AGENDADOR: 'AGE203', TOTAL : 5},
{ AGENDADOR: 'AGE028', TOTAL : 9},
],
totals = arr.reduce(function (r, o) {
(r[o.AGENDADOR])? r[o.AGENDADOR] += o.TOTAL : r[o.AGENDADOR] = o.TOTAL;
return r;
}, {});
console.log(totals);
arr.reduce(callback, [initialValue])
initialValue
Optional. Value to use as the first argument to the first call of the callback.

Using lodash:
var data; // the data represented by your screenshot
var counts = _.chain(data)
.groupBy('AGENDADOR')
.map(_.size)
.value();
counts will now be an object like this:
{
"AGE270": 9,
"AGE203": 5,
// etc
}

var sum = {};
yourArray.forEach(function(item) {
if(sum[item.AGENDADOR] === undefined) {
sum[item.AGENDADOR] = 0;
}
sum[item.AGENDADOR] += item.TOTAL
});
With this code, you'll have the total corresponding to each key in the sum object. Something like this:
{
AGE270: 9,
AGE203: 5,
AGE208: 9
}

Try this out:
function( data ){
var outputObj = {} ;
for(var i=0;i < data.length; i++){
datum = data[i];
if(outputObj[datum.AGENDADOR])
outputObj[datum.AGENDADOR] += parseInt( datum.TOTAL) ;
else
outputObj[datum.AGENDADOR] = parseInt( datum.TOTAL);
}
return outputObj;
};

How about a simple map() function? Like this:
var t = YourArray;
var u = t.map(function (a, i) { var g = {}; g[a.AGENDADOR] = a.TOTAL; return g; });

Related

Javascript - Adding multiple values to keys

I am trying to find the places of each letter in a sentence by using "dictionaries". The problem is I want to find all the places that each letter is and not only the last one. I am very new to JavaScript and couldn't figure out the way to do it.
function letters(stringArgument) {
stringArgument = stringArgument.replace(/ /g,'');
var dict = {};
for (var i=0; i < stringArgument.length; i++ )
if (!stringArgument[i] in dict){
dict[stringArgument[i]] = [];
}else{
dict[stringArgument[i]] = [i+1]
}
return dict
}
var a = letters('Lost time is never found again.');
console.log(a);
naturally gives this output:
{ L: [ 1 ], o: [ 17 ], s: [ 10 ], t: [ 5 ]...
but it should give this:
{ L: [ 1 ], o: [ 2, 17 ], s: [ 3, 10 ], t: [ 4, 5 ]...
Also each letter is saved to the dictionary at the same order they appear in the sentence, how can I order the letters alphabetically?
What you need is a function that gets the positions of a character in a given string.
Try this:
function findAllPositions(char, content) {
var result = [];
let index = content.indexOf(char);
while(index !== -1) {
result.push(index);
index = content.indexOf(char, index + 1);
}
return result;
}
findAllPositions('o', 'Lost time is never found again.'); // Result =  [1, 20]
Using this we can update the letter function as follows:
function letters(stringArgument) {
stringArgument = stringArgument.replace(/ /g, '');
var dict = {};
for (const char of stringArgument) {
dict[char] = findAllPositions(char, stringArgument)
}
return dict;
}
letters('is again.')
/*
{
"i": [0, 5],
"s": [1],
"a": [2, 4],
"g": [3],
"n": [6],
".": [7]
}
*/
You need to have
parantheses for the check
if (!(stringArgument[i] in dict)) {
create an array if the above is true
push the postion to the array
For getting a sorted output, you could take the entries of the object, apply a sorting by taking the key and show the result in order.
Object have an insertation oder for not positive 32 bit numbers (like indixes) or symbols. The index like numbers are sorted by value and appears first in the object.
function letters(stringArgument) {
stringArgument = stringArgument.replace(/ /g, '');
var dict = {};
for (var i = 0; i < stringArgument.length; i++) {
if (!(stringArgument[i] in dict)) {
dict[stringArgument[i]] = [];
}
dict[stringArgument[i]].push(i + 1);
}
return dict;
}
var a = letters('Lost time is never found again.');
Object
.entries(a)
.sort(([a], [b]) => a.localeCompare(b))
.forEach(([key, positions]) => console.log(key, ...positions));
console.log(a);
First, for any item, if it is not in an empty array:
var notInDict = !(stringArgument[i] in dict);
If not in dict, then initialize an empty array and push the item in it using
dict[stringArgument[i]].push(i + 1);
Try this.
function letters(stringArgument) {
stringArgument = stringArgument.replace(/ /g, "");
var dict = {};
for (var i = 0; i < stringArgument.length; i++) {
var notInDict = !(stringArgument[i] in dict);
if (notInDict) {
dict[stringArgument[i]] = [];
}
dict[stringArgument[i]].push(i + 1);
}
return dict;
}
var a = letters("Lost time is never found again.");
console.log(a);
you are assigning a new array at each iteration
dict[stringArgument[i]] = [i+1]
what you need to do is push the new position to existing array.
dict[stringArgument[i]].push(i+1)
also, remove the else block
function letters(stringArgument) {
stringArgument = stringArgument.toLowerCase().replace(/ /g,'');
var dict = {};
for (var i=0; i < stringArgument.length; i++ ){
if (!dict.hasOwnProperty(stringArgument[i])){
dict[stringArgument[i]] = [];
}
dict[stringArgument[i]].push(i+1);
}
//sorting
var letters = Object.keys(dict); //returns a array
letters.sort();
var sortedDic = {};
for(var i in letters) {
sortedDic[letters[i]] = dict[letters[i]];
}
return sortedDic;
}
var a = letters('Lost time is never found again.');
console.log(a);
for the first part you can also do that:
let sentence = 'Lost time is never found again.'
let tabLetters = [...sentence.replace(/ /g,'')].reduce((a,c,i)=>
{
if (!a[c]) a[c] = [i+1]
else a[c].push(i+1)
return a
},{})
document.write(JSON.stringify(tabLetters))

How to sort two dimensional array based on first array in Javascript

So, I have this array:
distances = [[Obj1, Obj2, Obj3, Obj4], [15,221,9,2]];
I want to sort the two dimensional array based on the second array so it should look like this:
distances = [[Obj4, Obj3, Obj1, Obj2], [2, 9, 15, 221]];
I know I can use this method: How to sort 2 dimensional array by column value?, but I can't seem to adapt the code.
First, a rather unefficient solution would be to transpose your array to match the layout of the solution you linked in your question.
var temp = [];
for(var i in distances[0])
temp[i] = ([distances[0][i], distances[1][i]]);
Then do the sorting and transform it back to its previous form:
distances = [[], []];
for (var i in temp) {
distances[0][i] = temp[i][0];
distances[1][i] = temp[i][1];
}
You could use a temporary array for the sort order and apply this to the two arrays of distances.
var distances = [['Obj1', 'Obj2', 'Obj3', 'Obj4'], [15, 221, 9, 2]],
order = distances[0].map(function (_, i) { return i; });
order.sort(function (a, b) {
return distances[1][a] - distances[1][b];
});
distances[0] = order.map(function (i) { return distances[0][i]; });
distances[1] = order.map(function (i) { return distances[1][i]; });
console.log(distances);
var sorted = distances[1].map(function (v, i) {
return {v:v,i:i,o:distances[0][i]} }).
sort(function (a,b) { return a.v - b.v});
distances[0] = sorted.map(function (x) { return x.o });
distances[1] = sorted.map(function (x) { return x.v });
var distances = [["Obj1", "Obj2", "Obj3", "Obj4"], [15,221,9,2]];
var NewDistances = [];
for (var i = 0; i < distances[0].length; i++)
NewDistances[i] = {
Obj: distances[0][i],
Key: distances[1][i]
};
NewDistances.sort(function(O1, O2) {
return O1.Key < O2.Key ? -1 : (O1.Key > O2.Key ? 1 : 0);
});
var Result = [[],[]];
for (var i = 0; i < NewDistances.length; i++) {
Result[0][i] = NewDistances[i].Obj;
Result[1][i] = NewDistances[i].Key;
}
console.log(Result);

Find minimum value in javascript?

I want to print the minimum variable 'name' in JS. Currently it prints the minimaum value. I rather want the variable name. For eg:- In the current code, it gives me 4, but I want c. How can I do this?
<script>
function myFunction()
{
var a = 5;
var b =10;
var c = 4;
document.getElementById("demo").innerHTML=Math.min(a,b,c);
}
</script>
Working DEMO
This should do the trick:
//Push values to object
var age = {};
age.a = 5;
age.b = 10;
age.c = 4;
var min = Infinity, name;
// Loop through object to get min value and then find relevant name
for(var x in age) {
if( age[x] < min) {
min = age[x];
name = x;
}
}
console.log ( 'property name is ' + name + ' and value is ' + min );
You could put your values in an array like
var values = [
{ name: 'a', value: 5 },
{ name: 'b', value: 10 },
{ name: 'c', value: 4 }
];
and then use the filter method with the hint from Ahmad's comment:
var min_value = Math.min.apply(null, values.map(function(item) {
return item.value;
}));
var min_name = values.filter(function (item) {
return item.value == min_value;
})[0].name;
See this fiddle for a working example.
Store the values in an array of objects. Each object will contain a name and value property. Then just iterate through the values and store the lowest.
var values = [
{
"name": "a",
"value": 5
},
{"name":"b",
"value":10
},
{
"name":"c",
"value":4
}
];
function min(arr){
var minValue = {};
for(var x = 0; x < arr.length; x++){
if(arr[x].value < minValue.value || !minValue.value){
minValue = arr[x];
}
}
return minValue.name;
};
document.getElementById("demo").innerHTML = min(values);
JS Fiddle: http://jsfiddle.net/AgMbW/
You can do this way:
var obj = {"names":["a","b","c"], "values":[5,10,4]}
var min = Math.min.apply( Math, obj["values"] );
var result = obj["names"][obj["values"].indexOf(min)];
document.getElementById("demo").innerHTML=result;
Here the fiddle: http://jsfiddle.net/eUcug/
Way 1 :
var x = 5;var getName = function(value){if(value === 5) return 'x'; else return null}
Way 2 :
NameValue.getName = function(value){for(i = 1;i<=2;i++){if(this["val" + i].value === value) {return this["val" + i].name;break;}console.log(this["val" + i]);}return null;}NameValue.val2 = {name : 'y',value : 1};NameValue.prototype.add({name : 'x',value : 10})
NameValue.getName(10); //return "x"
I hope you can understand how to find the variable name.

Javascript merge 2 arrays and sum same key values

I have 2 array:
var array1 = [[5,10],[6,10],[7,10],[8,10],[9,10]];
var array2 = [[1,10],[2,10],[3,10],[4,10],[5,40],[6,40]];
Want to get 1 merged array with the sum of corresponding keys;
var array1 = [[1,10],[2,10],[3,10],[4,10],[5,50],[6,50],[7,10],[8,10],[9,10]];
Both arrays have unique keys, but the corresponding keys needs to be summed.
I tried loops, concat, etc but can't get the result i need.
anybody done this before?
You can use .reduce() to pass along an object that tracks the found sets, and does the addition.
DEMO: http://jsfiddle.net/aUXLV/
var array1 = [[5,10],[6,10],[7,10],[8,10],[9,10]];
var array2 = [[1,10],[2,10],[3,10],[4,10],[5,40],[6,40]];
var result =
array1.concat(array2)
.reduce(function(ob, ar) {
if (!(ar[0] in ob.nums)) {
ob.nums[ar[0]] = ar
ob.result.push(ar)
} else
ob.nums[ar[0]][1] += ar[1]
return ob
}, {nums:{}, result:[]}).result
If you need the result to be sorted, then add this to the end:
.sort(function(a,b) {
return a[0] - b[0];
})
This is one way to do it:
var sums = {}; // will keep a map of number => sum
// for each input array (insert as many as you like)
[array1, array2].forEach(function(array) {
//for each pair in that array
array.forEach(function(pair) {
// increase the appropriate sum
sums[pair[0]] = pair[1] + (sums[pair[0]] || 0);
});
});
// now transform the object sums back into an array of pairs
var results = [];
for(var key in sums) {
results.push([key, sums[key]]);
}
See it in action.
a short routine can be coded using [].map()
var array1 = [[5,10],[6,10],[7,10],[8,10],[9,10]];
var array2 = [[1,10],[2,10],[3,10],[4,10],[5,40],[6,40]];
array1=array2.concat(array1).map(function(a){
var v=this[a[0]]=this[a[0]]||[a[0]];
v[1]=(v[1]||0)+a[1];
return this;
},[])[0].slice(1);
alert(JSON.stringify(array1));
//shows: [[1,10],[2,10],[3,10],[4,10],[5,50],[6,50],[7,10],[8,10],[9,10]]
i like how it's just 3 line of code, doesn't need any internal function calls like push() or sort() or even an if() statement.
Try this:
var array1 = [[5,10],[6,10],[7,10],[8,10],[9,10]];
var array2 = [[1,10],[2,10],[3,10],[4,10],[5,40],[6,40]];
var res = [];
someReasonableName(array1, res);
someReasonableName(array2, res);
function someReasonableName(arr, res) {
var arrLen = arr.length
, i = 0
;
for(i; i < arrLen; i++) {
var ar = arr[i]
, index = ar[0]
, value = ar[1]
;
if(!res[index]) {
res[index] = [index, 0];
}
res[index][1] += value;
}
}
console.log(JSON.stringify(res, null, 2));
So, the result may have holes. Just like 0th index. Use the below function if you want to ensure there are no holes.
function compact(arr) {
var i = 0
, arrLen = arr.length
, res = []
;
for(i; i < arrLen; i++) {
var v = arr[i]
;
if(v) {
res[res.length] = v;
}
}
return res;
}
So, you can do:
var holesRemoved = compact(res);
And finally if you don't want the 0th elem of res. Do res.shift();
Disclaimer: I am not good with giving reasonable names.
The simple solution is like this.
function sumArrays(...arrays) {
const n = arrays.reduce((max, xs) => Math.max(max, xs.length), 0);
const result = Array.from({ length: n });
return result.map((_, i) => arrays.map(xs => xs[i] || 0).reduce((sum, x) => sum + x, 0));
}
console.log(...sumArrays([0, 1, 2], [1, 2, 3, 4], [1, 2])); // 2 5 5 4

JS calculate mean of same elements in 2d array

I've got a 'table' of two columns represented as an array. The first column are numbers from 1 to 20 and they are labels, the second column are the corresponding values (seconds):
my_array = [ [ 3,4,5,3,4,5,2 ],[ 12,14,16,11,12,10,20 ] ];
I need the mean (average) for each label:
my_mean_array = [ [ 2,3,4,5 ],[ 20/1, (12+11)/2, (14+12)/2, (16+10)/2 ] ];
// edit: The mean should be a float - the notion above is just for clarification.
// Also the number 'labels' should remain as numbers/integers.
My try:
var a = my_array[0];
var b = my_array[1];
m = [];
n = [];
for( var i = 0; a.length; i++){
m[ a[i] ] += b[i]; // accumulate the values in the corresponding place
n[ a[i] ] += 1; // count the occurences
}
var o = [];
var p = [];
o = m / n;
p.push(n);
p.push(o);
How about this (native JS, will not break on older browsers):
function arrayMean(ary) {
var index = {}, i, label, value, result = [[],[]];
for (i = 0; i < ary[0].length; i++) {
label = ary[0][i];
value = ary[1][i];
if (!(label in index)) {
index[label] = {sum: 0, occur: 0};
}
index[label].sum += value;
index[label].occur++;
}
for (i in index) {
if (index.hasOwnProperty(i)) {
result[0].push(parseInt(i, 10));
result[1].push(index[i].occur > 0 ? index[i].sum / index[i].occur : 0);
}
}
return result;
}
FWIW, if you want fancy I've created a few other ways to do it. They depend on external libraries and are very probably an order of magnitude slower than a native solution. But they are nicer to look at.
It could look like this, with underscore.js:
function arrayMeanUnderscore(ary) {
return _.chain(ary[0])
.zip(ary[1])
.groupBy(function (item) { return item[0]; })
.reduce(function(memo, items) {
var values = _.pluck(items, 1),
toSum = function (a, b) { return a + b; };
memo[0].push(items[0][0]);
memo[1].push(_(values).reduce(toSum) / values.length);
return memo;
}, [[], []])
.value();
}
// --------------------------------------------
arrayMeanUnderscore([[3,4,5,3,4,5,2], [12,14,16,11,12,10,20]]);
// -> [[2,3,4,5], [20,11.5,13,13]]
or like this, with the truly great linq.js (I've used v2.2):
function arrayMeanLinq(ary) {
return Enumerable.From(ary[0])
.Zip(ary[1], "[$, $$]")
.GroupBy("$[0]")
.Aggregate([[],[]], function (result, item) {
result[0].push(item.Key());
result[1].push(item.Average("$[1]"));
return result;
});
}
// --------------------------------------------
arrayMeanLinq([[3,4,5,3,4,5,2], [12,14,16,11,12,10,20]]);
// -> [[3,4,5,2], [11.5,13,13,20]]
As suspected, the "fancy" implementations are an order of magnitude slower than a native implementation: jsperf comparison.
var temp = {};
my_array[0].map(function(label, i) {
if (! temp[label])
{
temp[label] = [];
}
temp[label].push(my_array[1][i]);
});
var result = [ [], [] ];
for (var label in temp) {
result[0].push(label);
result[1].push(
temp[label].reduce(function(p, v) { return p + v }) / temp[label].length
);
}
This function do not sort the resulted array like in your result example. If you need sorting, just say me and i will add it.
function getMeanArray(my_array)
{
m = {}; //id={count,value}
for( var i = 0; i<my_array[0].length; i++){
if (m[my_array[0][i]]===undefined)
{
m[my_array[0][i]]={count:0, value:0};
}
m[ my_array[0][i] ].value += my_array[1][i]; // accumulate the values in the corresponding place
m[ my_array[0][i] ].count++; // count the occurences
}
var my_mean_array=[[],[]];
for (var id in m)
{
my_mean_array[0].push(id);
my_mean_array[1].push(m[id].count!=0?m[id].value/m[id].count:0);
}
return my_mean_array;
}

Categories