I want to perform the sum operation on each subarray using javascript using forEach,map,reduce function, so that ultimately my output should look like:
sum = [8,13,22]
but I am not getting the desired output. Please assist where I am going wrong.Thanks.
var Data = [{"a":1,"b":2,"c":5},{"a":3,"b":4,"c":6},{"a":6,"b":7,"c":9}];
var newArr = [];
Data.forEach(function(item) {
item = item.reduce(function(a, b) {
return a + b;
});
newArr.push([item]);
});
console.log(newArr);
You could map the summed values, literately.
var data = [{ a: 1, b: 2, c: 5 }, { a: 3, b: 4, c: 6 }, { a: 6, b: 7, c: 9 }],
result = data.map(o => Object.values(o).reduce((a, b) => a + b));
console.log(result);
Just some annotation to the given code:
You can not iterate an object with reduce, because that works only for array. To overcome this problem, you need just the values of the object by taking Object.values and then, you could iterate the values.
Then return the sum without wrapping it in an array.
var Data = [{"a":1,"b":2,"c":5},{"a":3,"b":4,"c":6},{"a":6,"b":7,"c":9}];
var newArr = [];
Data.forEach(function(item) {
var sum = Object.values(item).reduce(function(a, b) {
return a + b;
});
newArr.push(sum);
});
console.log(newArr);
A better solution would be the use of Array#map, because you need one value for each element of the array.
var data = [{"a":1,"b":2,"c":5},{"a":3,"b":4,"c":6},{"a":6,"b":7,"c":9}];
newArr = data.map(function(item) {
return Object.values(item).reduce(function(a, b) {
return a + b;
});
});
console.log(newArr);
As per your example, Old way
var Data = [{"a":1,"b":2,"c":5},{"a":3,"b":4,"c":6},{"a":6,"b":7,"c":9}];
var newArr = [];
Data.forEach(function(object) {
let sum = 0;
for (var property in object) {
if (object.hasOwnProperty(property)) {
sum += object[property]
}
}
newArr.push(sum);
});
console.log(newArr);
Related
So as the question states, I'm attempting to write a function for which the input can be either an Array or an Object (as well as a callback to test them against).
The desired return value is an Array / Object of the elements (value/key pairs in the case of the Object) that passed the test - but the original Array / Object should be updated to remove those elements.
For example - if you passed in an "isEven" callback function that determines if numbers are even, then the expected results would be:
let a = [1, 2, 3, 4]
reject(a)
//Output:
[2, 4]
console.log(a);
//expected output
[1, 3]
So far I've been trying to write an conditional scenario based on Array.isArray(input), to use one set of code for handling arrays, another set for handling objects. However, it's been not working properly for objects, and I'm curious if there'd be one way to write it that would work for both cases? If not what might be the best approach here?
My rough attempt to this point, if the code is helpful:
function reject(collection, callback) {
let newArr;
if (!collection.constructor == Array) {
newArr = {};
for (let [key, value] of Object.entries(collection)) {
if (!callback(value)) {
newArr[key] = value;
}
}
} else {
newArr = [];
for (let el of collection) {
if (!callback(el)){
newArr.push(el);
}
}
}
return newArr;
}
You can use Array.isArray to check if an object is an array. To remove elements from the array, you can iterate backwards and use Array#splice.
function reject(o, f) {
if (Array.isArray(o)) {
let res = [];
for (let i = o.length - 1; i >= 0; i--)
if (f(o[i])) res.push(o.splice(i, 1)[0]);
return res.reverse();
}
let res = {};
for (const [k, v] of Object.entries(o))
if (f(v)) {
res[k] = v;
delete o[k];
}
return res;
}
let a = [1, 2, 3, 4];
console.log(reject(a, x => x % 2 === 0), a);
let obj = {a : 1, b : 2, c : 3, d : 4};
console.log(reject(obj, x => x > 2), obj);
Suppose I generate two arrays
One that holds Array of numbers:
[5.65, 3.25, 4.34, 6.78]
And another array that holds objects with some information in them
[car.object1, car.object2, car.object3, car.object4]
And the objects in second array are related to the numbers in first array. So object1 is related to 5.65, object2 to 3.25 and so on.
So I want to sort the array 1 in an ascending order and at the same time sort the array 2 also.
So the result should be:
[3.25, 4.34, 5.65, 6.78]
&
[car.object2, car.object3, car.object1, car.object4]
My Approach: (You can just ignore the below answer as I think it is wrong. It does not work.)
var all = [];
var A = [5.65, 3.25, 4.34, 6.78];
var B = ['store.object1', 'store.object2', 'store.object3', 'store.object4'];
for (var i = 0; i < B.length; i++) {
all.push({
'A': A[i],
'B': B[i]
});
}
all.sort(function(a, b) {
return a.A - b.A;
});
A = [];
B = [];
for (var i = 0; i < all.length; i++) {
A.push(all[i].A);
B.push(all[i].B);
}
console.log(A, B);
You could use a temporary array with the indices and sort it with the values of the first array. Then map the sorted array with the values of array1 and array2.
I use strings for the second array, instead of missing objects.
var array1 = [5.65, 3.25, 4.34, 6.78],
array2 = ['car.object1', 'car.object2', 'car.object3', 'car.object4'],
temp = array1.map(function (_, i) { return i; });
temp.sort(function (a, b) { return array1[a] - array1[b]; });
array1 = temp.map(function (a) { return array1[a]; });
array2 = temp.map(function (a) { return array2[a]; });
console.log(temp);
console.log(array1);
console.log(array2);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Unless you want to implement the sort yourself, one simple way is to combine the entries from the number array with the entries from the object array (at least briefly), sort that, and then (if necessary) extract the result:
// Setup
var car = {
object1: {name: "object1"},
object2: {name: "object2"},
object3: {name: "object3"},
object4: {name: "object4"}
};
var nums = [5.65, 3.25, 4.34, 6.78];
var objs = [car.object1, car.object2, car.object3, car.object4];
// Combine
var joined = [];
nums.forEach(function(num, index) {
joined[index] = {num: num, object: objs[index]};
});
// Sort
joined.sort(function(a, b) {
return a.num - b.num;
});
// Extract
nums = [];
objs = [];
joined.forEach(function(entry, index) {
nums[index] = entry.num;
objs[index] = entry.object;
});
console.log(nums);
console.log(objs);
.as-console-wrapper {
max-height: 100% !important;
}
But rather than combine, sort, and extract, I'd probably just maintain a single array and add each number to its relevant object, so they always travel together.
Here is an ES6 way to do it:
let a = [5.65, 3.25, 4.34, 6.78];
let b = [{ x:1 }, { x:2 }, { x:3 }, { x: 4}];
[a, b] = a.map( (n, i) => [n, b[i]] ) // zip the two arrays together
.sort( ([n], [m]) => n-m ) // sort the zipped array by number
.reduce ( ([a,b], [n, o]) => [[...a, n], [...b, o]], [[],[]] ); // unzip
console.log(JSON.stringify(a));
console.log(JSON.stringify(b));
I've helped myself with an object containing car.object as the key and it's number as the value. Seems easy&quick solution.
var obj = [{'car.object1': 5.65}, {'car.object2': 3.25}, {'car.object3': 4.34}, {'car.object4': 6.78}],
objs = obj.sort((a,b) => a[Object.keys(a)] - b[Object.keys(b)]);
console.log(objs.map(v => Object.keys(v)[0]));
console.log(objs.map(v => v[Object.keys(v)]));
console.log(objs);
.as-console-wrapper {
max-height: 100% !important;
}
My js object:
data_obj = {'p1': 1, 'p2':2, 'p3':3}
my array
data_array = ['p1', 'p3']
Now, I want to filter the object based on the array. Expected result is
fil_obj = {'p1': 1, 'p3':3}
Now then, find the key having a maximum value. Expected result is
p3
Since I have object with thousands of items, I expect a very efficient solution.
Since I'm using d3js for this project, solution based on d3js like d3.max would be great.
You could iterate the wanted properties and return the max key.
var data_obj = { p1: 1, p2: 2, p3: 3},
data_array = ['p1', 'p3'],
result = data_array.reduce(function (r, a, i) {
return !i || data_obj[r] < data_obj[a] ? a : r;
}, undefined);
console.log(result);
I've never used d3, but it seems to me you can get the result pretty efficiently with a single call to .reduce():
var data_obj = {'p1': 1, 'p2':2, 'p3':3};
var data_array = ['p1', 'p3'];
var results = data_array.reduce((r,v)=>{
if (v in data_obj) {
r.data[v] = data_obj[v];
if (data_obj[v] > r.maxVal) {
r.maxKey = v;
r.maxVal = data_obj[v];
}
}
return r;
}, {data:{}, maxKey:null, maxVal:Number.NEGATIVE_INFINITY});
console.log(results);
I have arrays like [a], [a,b], [a,b,c] and so on.
How can I convert them into [a], [a][b], [a][b][c] and so on?
Example:
var arr = [1,2,3,4];
arr = do(arr); // arr = arr[1][2][3][4]
You could map it with Array#map.That returns an array with the processed values.
ES6
console.log([1, 2, 3, 4].map(a => [a]));
ES5
console.log([1, 2, 3, 4].map(function (a) {
return [a];
}));
While the question is a bit unclear, and I think the OP needs possibly a string in the wanted form, then this would do it.
console.log([1, 2, 3, 4].reduce(function (r, a) {
return r + '[' + a + ']';
}, 'arr'));
Functional:
use .map like this
[1,2,3,4].map(i => [i])
Iterative:
var list = [1, 2, 3, 4], result = [];
for (var i=0; i<list.length; i++) {
result.push([list[i]]);
}
If I understand you correctly, you are converting single dimension array to multi dimensional array.
To do so,
var inputArray = [1,2,3,4];
var outputArray = [];
for(var i=0;i<inputArray.length;i++)
{
outputArray.push([inputArray[i]])
}
function map(arr){
var aux = [];
for(var i=0; i<arr.length;++i){
var aux2 = [];
aux2.push(arr[i]);
aux.push(aux2);
}
return aux;
}
I have 2 arrays, a type array and an amount array:
var type = ["AB", "AB", "K1"];
var amt = [5, 2, 3];
I am having a difficult time grouping them together.
I want the output to be an array like below:
final_array = [{"AB", 7}, {"K1", 3}];
/* 7 and 3 are the sum of each type */
Note: I am guaranteed that both arrays will be the same size, and also guaranteed the order which means type[i] belongs with amt[i]. So from the example above type[0] which is "AB" belongs with amt[0] which is 5.
Thanks
This is written verbosely, but you'd use an object, and then iterate over one array checking if the keys exist in the object, if they do, just add the value to the sum, if they don't, set the value as the sum etc.
var type = [ "AB", "AB", "K1"];
var amt = [5, 2, 3];
var map = {};
type.forEach(function(x, i) {
if (x in map) {
map[x] += amt[i];
} else {
map[x] = amt[i];
}
});
document.body.innerHTML = '<pre>' + JSON.stringify(map, 0, 4) + '</pre>';
That leaves you with an object like {AB: 7, K1: 3}, which is probably what you want, but if you just have to have an array with objects that can't be looked up easily, you'd do
var arr = Object.keys(map).map(function(x) {
var o = {};
o[x] = map[x];
return o;
});
and you have [{"AB": 7}, {"K1": 3}]
var type = ["AB", "AB", "K1"];
var amt = [5, 2, 3];
var obj = {};
var final_array = [];
type.forEach(function(v, i) {
var t = obj[v];
if (t) {
t[v] += amt[i];
} else {
t = {};
t[v] = amt[i];
obj[v] = t;
}
});
Object.keys(obj).forEach(function(e) {
final_array.push(obj[e]);
});
document.write(JSON.stringify(final_array));