Javascript merge 2 arrays and sum same key values - javascript

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

Related

Can I modify a for...of loop's variable? [duplicate]

I'm trying to square each number in an array and my original code didn't work. I looked up another way to do it, but I'd like to know WHY the original code didn't work.
Original code:
function(arr) {
ret= [];
for (var i = 0, len = arr.length; i < len; i++) {
root = Math.sqrt(arr[i]);
ret.push(root);
}
return ret;
}
Working Code:
function(arr) {
ret= [];
for (var i = 0, len = arr.length; i < len; i++) {
ret.push(arr[i] * arr[i]);
}
return ret;
}
Math.sqrt gives you square root not square of a number. Use Math.pow with second argument of 2.
How about that ?
function (arr) {
return arr.map(function (x) {
return Math.pow(x, 2);
});
}
Array.map(func) applies the function to each element of the map and returns the array composed of the new values.
Math.pow(base, exp) raises base to its exp power.
The first sample is taking the square root, not squaring the value. To square you want to use
Math.pow(arr[i],2);
Here is how it can be done, using a simple method called .forEach
var numbers = [1,2,3,4,5,6,7,8];
numbers.forEach(function(element, index, array){
array[index] = element* element;
});
console.log(numbers);
Best way to Square each number in an array in javascript
Array.prototype.square = function () {
var arr1 = [];
this.map(function (obj) {
arr1.push(obj * obj);
});
return arr1;
}
arr = [1, 6, 7, 9];
console.log(arr.square());
arr1 = [4, 6, 3, 2];
console.log(arr1.square())
Here is the function write with ES6 Exponentiation (**):
let arr = [1, 6, 7, 9];
let result = arr.map(x => x ** 2);
console.log(result);
The original code is taking the square root of the value. The second version is multiplying the value with itself (squaring it). These are inverse operations
I hope this answers your question
const numbers = [1,2,3,4,5,6,7,8,9];
for(let squareIt of numbers){
console.log(Math.pow(squareIt, 2));
}
Resolved by kiss-barnabas
Use embedded for , for pretty syntax :
var arr=[1,2,3,4] ;
[for (i of arr) i*i ];
//OUT : > [1,4,9,16]
Declarative Programming :)
let list = [1,2,3,4,5,6,7,8,9,10];
let result = list.map(x => x*x);
console.log(result);
Avoid unnecessary loops, use map()function
let array = [1,2,3,4,5];
function square(a){ // function to find square
return a*a;
}
arrSquare = array.map(square); //array is the array of numbers and arrSquare will be an array of same length with squares of every number
You can make the code shorter like this:
let array = [1,2,3,4,5];
arrSquare = array.map(function (a){return a*a;});
let arr = [1, 2, 3];
let mapped = arr.map(x => Math.pow(x, 2));
console.log(mapped);
This should work.
let kiss=[3,4,5,6];
let arra=[];
for(o in kiss){
arra.push(kiss[o]*kiss[o])
}
console.log(kiss=arra)
using array square root of the first number is equal to the cube root of the second number
function SquareAndCube(arr) {
let newarr = [];
for(i=0 ; i<arr.length; i++) {
if(Math.sqrt(arr[0])/2 === Math.cbrt(arr[1])/2 ) {
return true;
} else return false;
}
}
console.log(SquareAndCube([36, 215]))
This should work with the .map() method:
const number = [2, 6, 6, 2, 8, 10];
const squareNumber = number.map(num => num*num);
console.log(squareNumber);
function squareDigits(num){
//may the code be with you
var output = [];
var splitNum = num.toString();
for(var i = 0; i < splitNum.length; i++){
output.push(splitNum.charAt(i))
}
function mapOut(){
var arr = output;
return arr.map(function(x){
console.log(Math.pow(x, 2));
})
}
mapOut();
}
squareDigits(9819);
This should work
This will work
const marr = [1,2,3,4,5,6,7,8,9,10];
console.log(marr.map((x) => Math.pow(x, 2)));
function map(square,a) {
var result = [];
for(var i=0;i<=a.length-1;i++)
result[i]=square(a[i]);
return result;
}
var square = function(x) {
return x*x;
}
var value=[1,2,3,4];
var final= map(square,value);
console.log(final);
You can also try the above code snippet.

Inconsistency, when returning index of duplicate values

I'm trying to create an algorithm to find duplicate values in a list and return their respective indexes, but the script only returns the correct value, when I have 2 equal elements:
array = [1,2,0,5,0]
result -> (2) [2,4]
Like the example below:
array = [0,0,2,7,0];
result -> (6) [0, 1, 0, 1, 0, 4]
The expected result would be [0,1,4]
Current code:
const numbers = [1,2,0,5,0];
const checkATie = avgList => {
let averages, tie, n_loop, currentAverage;
averages = [... avgList];
tie = [];
n_loop = 0;
for(let n = 0; n <= averages.length; n++) {
currentAverage = parseInt(averages.shift());
n_loop++
for(let avg of averages) {
if(avg === currentAverage) {
tie.push(numbers.indexOf(avg),numbers.indexOf(avg,n_loop))
};
};
};
return tie;
}
console.log(checkATie(numbers));
if possible I would like to know some way to make this code more concise and simple
Use a Set
return [...new Set(tie)]
const numbers1 = [1,2,0,5,0];
const numbers2 = [0,0,2,7,0];
const checkATie = avgList => {
let averages, tie, n_loop, currentAverage;
averages = [... avgList];
tie = [];
n_loop = 0;
for(let n = 0; n <= averages.length; n++) {
currentAverage = parseInt(averages.shift());
n_loop++
for(let avg of averages) {
if(avg === currentAverage) {
tie.push(avgList.indexOf(avg),avgList.indexOf(avg,n_loop))
};
};
};
return [...new Set(tie)]
}
console.log(checkATie(numbers1));
console.log(checkATie(numbers2));
I hope this help you.you can use foreach function to check each item of array
var array = [0,0,2,7,0];
var result = [] ;
array.forEach((item , index)=>{
if(array.findIndex((el , i )=> item === el && index !== i ) > -1 ){
result.push(index)
}
})
console.log(result);
//duplicate entries as an object
checkDuplicateEntries = (array) => {
const duplicates = {};
for (let i = 0; i < array.length; i++) {
if (duplicates.hasOwnProperty(array[i])) {
duplicates[array[i]].push(i);
} else if (array.lastIndexOf(array[i]) !== i) {
duplicates[array[i]] = [i];
}
}
console.log(duplicates);
}
checkDuplicateEntries([1,2,0,5,0]);
// hope this will help
Create a lookup object with value and their indexes and then filter all the values which occurred more than once and then merge all indexes and generate a new array.
const array = [1, 2, 0, 5, 0, 1, 0, 2],
result = Object.values(array.reduce((r, v, i) => {
r[v] = r[v] || [];
r[v].push(i);
return r;
}, {}))
.filter((indexes) => indexes.length > 1)
.flatMap(x => x);
console.log(result);

how to print a unique number in a array

The problem is to find the unique number in a array such as [2,2,2,5].
The output should be 5 as it is the 1 unique element in the array.
I have attempted this:
function findUniq(arr) {
var b= arr[0];
var c;
for(var i=0; i<arr.length; i++)
{
if(arr[i]===b )
{
b=arr[i]
}
else
{
c=arr[i];
}
}
return c
console.log(findUniq([3, 5, 3, 3, 3]))
This works fine unless the unique number is the first element in the array. How do I fix this?
You can use indexOf and lastIndexOf to see if a value occurs more than once in the array (if it does, they will be different), and if so, it is not the unique value. Use filter to process the array:
let array = [2,2,2,5];
console.log(array.filter(v => array.indexOf(v) === array.lastIndexOf(v)));
array = [5,3,3,3,3];
console.log(array.filter(v => array.indexOf(v) === array.lastIndexOf(v)));
array = [4,4,5,4];
console.log(array.filter(v => array.indexOf(v) === array.lastIndexOf(v)));
You can create a recursive function that will take the first element of the array and see if it exists in the rest of it, if it does, it will take the next element and do the same, return the element if it doesn't exist in the rest of the array :
const arr = [3, 3, 3, 5, 3];
const find = arr => {
const [f, ...rest] = arr;
if(rest.includes(f))
return find(rest);
else
return f;
}
const result = find(arr);
console.log(result);
Note that this will return the last element if all of them are the same [3,3,3] will return 3
Try something like this using a set, which only stores unique elements:
var set = new Set(arr);
// count instances of each element in set
result = {};
for(var i = 0; i < a.length; ++i) {
if(!result[arr[i]])
result[arr[i]] = 0;
++result[arr[i]];
}
for (var value in result) {
if (value == 1) {
return value;
}
}
// if there isn't any
return false;
This should work, please tell me if it doesn't.
This is another implementation that is surely less efficient than that of #Nick's, but it is a valid algorithm anyway:
function findUniq(arr) {
var elemCount = new Map();
var uniq = [];
// Initialize elements conts
for (var k of arr.values()) {
elemCount.set(k, 0);
}
// Count elements
for (var k of arr.values()) {
elemCount.set(k, elemCount.get(k) + 1);
}
// Add uniq elements to array
for (var [k, v] of elemCount.entries()) {
if (v === 1) uniq.push(k);
}
return uniq;
}
console.log(findUniq([3, 5, 3, 3, 3]))
if you prefer .reduce over .map for your use case (for performance/etc. reasons):
function existance(data) {
return data.reduce((a, c) => (data.indexOf(c) === data.lastIndexOf(c)) ? a.concat(c) : a, []);
}
console.log(existance([1,1,1,2]));
console.log(existance([1,1,2,3,4,5,5,6,6,6]));

How to split an array into multple arrays each with a unique name

I have an array = [A,1,0,1,0,1,B,1,0,0,1,A,1]
I need to split this array into multiple arrays. The split will occur at the "A" or "B" position as seen in the new arrays below. The names of the new arrays use the string "group" plus an incremented number starting with 1 or 0.
The end result should look like:
group1 = [A,1,0,1,0,1]
group2 = [B,1,0,0,1]
group3 = [A,1]
I can get the section of the array I need by creating an array (arrTemp), so I can store the positions (indexes) and later use slice() to get the sections I want (A,1,0,1,0,1), (A,1,0,0,1), and (A,1). But I don't know how to store the results of my slice()'s in arrays with unique names incremented by 1.
This is what I have tried so far:
var arr = [A,1,0,1,0,1,B,1,0,0,1,A,1];
arr.forEach(myFunction)
function myFunction(item, index) {
if ((item=="A") || (item=="B")) {
arrTemp.push(index);
arrTemp=arrTemp; //not sure I need this. I did this so it array would be global
}
}
for (var i = 0; i < arr.length; i++){
sectArray = arr.slice(arrTemp[i]+1,arrTemp[i + 1])
'group' + [i] = [arrTemp[i],sectArray]; //here is my problem.
}
It seems like you're trying to dynamically create variables. That seems tricky and probably won't work. What you should probably have is some collection of results. Probably a parent array that holds all of them.
For example:
var containerArray = [];
Then:
for (var i = 0; i < arr.length; i++){
sectArray = arr.slice(arrTemp[i]+1,arrTemp[i + 1])
containerArray[i] = [arrTemp[i],sectArray];
}
Now containerArray will have all of your stuff. You can also do this with an object:
var containerObject = {};
And the same thing after.
you only need one loop here, keep an empty temp array, iterate over arr and keep pushing elements in temp each time you see 'A' or 'B' push temp to final array, and at last push temp once more into final array because last section will be left.
var arr = ['A',1,0,1,0,1,'B',1,0,0,1,'A',1];
var temp = [];
var sectArray = [];
arr.forEach(myFunction)
function myFunction(item, index) {
if (((item=="A") || (item=="B")) && temp.length) {
sectArray.push(temp);
temp = [item];
}else{
temp.push(item);
}
}
sectArray.push(temp);
console.log(sectArray);
Check this solution that use a combination of string and array methods:
var data = ['A',1,0,1,0,1,'B',1,0,0,1,'A',1];
var results = data.toString().split(/(?=[a-zA-Z]+)/)
.map(function(value){
return value.split(',').filter(function (item) {
return item.length ? true: false;
})
})
.map(function(item) {
return item.map(function (value) {
return isNaN(parseInt(value)) ? value : parseInt(value);
})
});
console.log(results);
// results = [["A", 1, 0, 1, 0, 1], ["B", 1, 0, 0, 1], ["A", 1]]
Another solution using Array#reduce function.
var x = ["A", 1, 0, 1, 0, 1, "B", 1, 0, 0, 1, "A", 1];
function reformat(arr) {
var smallArrCounter = 0;
return arr.reduce(function (acc, item) {
if (item === "A" || item === "B") {
acc["group" + (++smallArrCounter)] = [item];
} else {
acc["group" + smallArrCounter].push(item);
}
return acc;
}, {});
}
var result = reformat(x);
console.log(result.group1); // ["A", 1, 0, 1, 0, 1]
console.log(result.group2); // ["B", 1, 0, 0, 1]
console.log(result.group3); // ["A", 1]
There may be a more performant approach that doesn't require two iterations of the array, but my thought is:
Determine the indices of the group delimiters (characters)
Slice the array into groups based on those delimiters, using either the next index as the end, or arr.length if slicing the last group
This has the assumption that the array delimiters may not be known in advance.
const charIndices = [];
const groups = [];
const arr = ['A',1,0,1,0,1,'B',1,0,0,1,'A',1];
// get the indices of the characters
arr.forEach((v, i) => ('' + v).match(/[A-Z]+/) ? charIndices.push(i) : undefined);
// use the found indices to split into groups
charIndices.reduce((a, b, i) => {
a.push(arr.slice(b, charIndices[i+1] ? charIndices[i+1]-1 : arr.length));
return a;
}, groups);
console.log(groups);

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);

Categories