Sort an array of arrays in JavaScript - javascript

I'm trying to sort an array of arrays with integers inside, for example:
var array = [[123, 3], [745, 4], [643, 5], [643, 2]];
How can I sort it in order to return something like the following?
array = [[745, 4], [643, 2], [643, 5], [123, 3]];

You can pass a custom comparison function to Array.prototype.sort(), like so:
var sortedArray = array.sort(function(a, b) { return a - b; });
This would sort an array of integers in ascending order. The comparison function should return:
an integer that is less than 0 if you want a to appear before b
an integer that is greater than 0 if you want b to appear before a
0 if a and b are the same
So, for this example you would want something like:
var sortedArray = array.sort(function(a, b) {
return b[0] - a[0];
});
If you wanted to sort on both elements of each sub-array (ie. sort by the first element descending, then if they are the same then sort by the second element descending), you could do this:
var sortedArray = array.sort(function(a, b) {
if (a[0] == b[0]) {
return a[1] - b[1];
}
return b[0] - a[0];
});
See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort for more info.

You can use sort method and first sort by first elements and then by second.
var array = [[123, 3], [745, 4], [643, 5], [643, 2]];
array.sort(([a, b], [c, d]) => c - a || b - d);
console.log(array)

Assuming you want to sort by the first index in your example, the sort function exists to solve your problem.
let ans = [[123, 3], [745, 4], [643, 5], [643, 2]].sort( (a, b) => {
return b[0] - a[0]
})
console.log(ans)

A solution for the arrays with generic lengths (not limited to 2 or equal) can be as below:
array.sort((a,b)=>
{
for(let i=0;i<a.length && i<b.length;i++){
if(a[i]!==b[i]){
return a[i]-b[i];
}
}
return a.length-b.length;
};

Related

Find average of each array within an array

I'm trying to write a map/reduce to get the average of each array within an array.
For example.
[[1][2,3][4,5,6,7]] => [1, 2.5, 5.5]
Right now this is my code where result is the array of arrays:
result.map(array => {
return array.reduce((a, b) => (a + b)) / array.length;
})
const result = [
[1],
[2, 3],
[4, 5, 6, 7]
]
console.log(result.map(array => {
return array.reduce((a, b) => (a + b)) / array.length;
}))
Any help to get the desired output is much appreciated. As it stands, my output is reducing to an array of NaN's instead of the averages.
You need a closing parentesis.
By using Array#reduce with arrays with unknown length, you need to take a start value, which is in this case of a length of zero the result.
var result = [[1], [2, 3], [4, 5, 6, 7]],
avg = result.map(array => array.reduce((a, b) => a + b, 0) / array.length);
// ^^^ ^
// optional required
console.log(avg);
you must provide a second argument to the reduce function, the initial value of a. So:
result.map(array => {
return array.reduce((a, b) => a + b, 0) / array.length;
});
You may also want to ensure that array.length > 0 before you divide by it

forEach() and reduce() not working with arguments

I have two arrays (a,b) and my task is to find the difference of their volumes i.e. i have to multiply all elements of array a, then do the same for array b and then subtract the two to find the difference.
I tried using forEach() and reduce() in conjuction with arguments but it seems that the last element of each array is left out and what I get as output is NaN.
This is my code
function findDifference(a, b) {
var args = Array.prototype.slice.call(arguments);
var results = [];
args.forEach(function(argument){
return argument.reduce(function(a,b){
results.push(a*b);
});
});
return results;
}
and this is my output for findDifference([3, 2, 5], [1, 4, 4]);
[6, NaN, 4, NaN]
Looks like the multiplication stops with the second element of each array. Any ideas?
Why not just multiply the given arrays and take the delta of the results?
function findDifference(a, b) {
return [a, b]
.map(a => a.reduce((a, b) => a * b))
.reduce((a, b) => a - b);
}
console.log(findDifference([3, 2, 5], [1, 4, 4]));
With arguments.
function findDifference(a, b) {
return Array.prototype
.map.call(arguments, a => a.reduce((a, b) => a * b))
.reduce((a, b) => a - b);
}
console.log(findDifference([3, 2, 5], [1, 4, 4]));
Instead of storing each multiplication in result array, you can store the result of all the multiplication of each array in result array.
function findDifference(a, b) {
var args = Array.prototype.slice.call(arguments);
var results = [];
args.forEach(function(argument){
results.push(argument.reduce(function(a,b){
return a*b;
}));
});
return results;
}
console.log(findDifference([3, 2, 5], [1, 4, 4]));

What's an effective way to merge arrays based on the nth element?

This is relatively straightforward, but it's bugging me that I can't find a more elegant solution.
Say you have an array of n-dimensional arrays, and you want to just squash together the arrays that have a matching mth, element by some method, let's say addition.
Example: [[1, 100], [1, 200], [2, 100], [2, 105], [3, 202], [4, 133]]
Result:
[[1, 300], [2, 205], [3, 202], [4, 133]]
The solution I came up with seems really inelegant to me. Is there some way to do this with way less code, or in a much more efficient way?
function mergePairs(originalArray) {
const newArray = [];
originalArray.forEach((pair) => {
const foundPair = newArray.find((newPair) => {
return newPair[0] === pair[0];
});
if (foundPair) {
foundPair[1] += pair[1];
} else {
newArray.push(pair);
}
});
return newArray;
}
Aside: If there's a cheeky one-liner in lodash that accomplishes the same thing in a super inefficient way, I'm happy with that too.
You might use reduce and map for your specific case:
function mergePairs (originalArray) {
const o = originalArray.reduce((a, e) => (a[e[0]] = ~~a[e[0]] + e[1]) && a, {});
return Object.keys(o).map(k => [+k, o[k]]);
}
console.log(mergePairs ([[1, 100], [1, 200], [2, 100], [2, 105], [3, 202], [4, 133]]))
Personally I find it makes more sense to split the pairs up then recombine. I use indexOf the matching array as it is more efficient to look through than the entire original array list. Each time I come across a new value, I add it to match list. The match values can be anything, not just numbers, and don't have to avoid any keywords. The ~ converts -1 from not found into 0 which is falsey.
function combine (complexArray){
var matches = [];
var totals = [];
complexArray.forEach(simplify);
function simplify(item) {
var match = matches.indexOf(item[0]);
if(~match) {
totals[match] += item[1];
} else {
matches.push(item[0]);
totals.push(item[1]);
}
}
return matches.map(function(value, index) {
return [value, totals[index]];
});
}
If you are only sorting numbers, and you expect the array to be sorted in ascending order already (like your example):
function mergePairs(arr) {
return arr.sort((a, b) => {
if (a[0] === b[0]){
a[1] += b[1];
b[0] = 'del'
}
}).filter(val => val[0] !== 'del');
}
Or you could sort it to be safe:
function mergePairs(arr) {
arr.sort((a, b) => a[0] === b[0]);
return arr.sort((a, b) => {
if (a[0] === b[0]){
a[1] += b[1];
b[0] = 'del'
}
}).filter(val => val[0] !== 'del');
}

How i can substract and sum results all arrays in array

I have a few arrays in array :
([[10,0],[3,5],[5,8]])
I try substract all inner arrays a - b and then sum results ( example : 10 - 0 = 10, 3-5 = -2, 5-8 = -3, 10+(-2)+(-3) = 5;
My try:
var el;
return array.reduce((a, b) => a - b );
But my result came out Nan, now Im understood, in my code i want substring array from array - bad idea.
I know how do this with using for or something like that, my question is:
how i can do this with use reduce or other ''modern'' method?
Thanks for help.
PS sorry for my English skill ;)
You can use reduce() method like this.
var data = [[10,0],[3,5],[5,8]]
var result = data.reduce((r, e) => r + (e[0] - e[1]), 0);
console.log(result)
Flexible solution, the size of the nested arrays doesn't matter, it will still return a proper result.
const count = (arr) => arr.reduce((s, v) => {
s += v.reduce((a,b) => a - b);
return s;
}, 0);
let arr1 = [ [10, 0], [3, 5], [5, 8] ],
arr2 = [ [5, 4, 1], [3, 5, 5], [5, 8] ];
console.log(count(arr1));
console.log(count(arr2));
Something like this? You were close, but be sure to have an initial value of 0 and dereference the inner arrays into a and b like so:
var array = [[10,0],[3,5],[5,8]];
var result = array.reduce((prev, [a, b]) => prev + (a - b), 0);
console.log(result);
const arr = ([[10,8],[3,5],[5,8]]);
arr.map(pair => pair[0] - pair[1]).reduce((a,b) => a + b)
You could reduce the outer and inner arrays.
var array = [[10, 0], [3, 5], [5, 8]],
result = array.reduce(function (r, a) {
return r + a.reduce(function (x, y) {
return x - y;
})
}, 0);
console.log(result);

javascript - Get largest value(s) in multi-dimensional array

I am using this tutorial to get the largest 'first' [0] value of a multidimensional array.
array = [[1, 5], [4, 7], [3, 8], [2, 3],
[12, 4], [6, 6], [4, 1], [3, 2],
[8, 14]]
array.reduce(function(max, arr) {
return max >= arr[0] ? max : arr[0];
}, -Infinity);
but how can i get other associated values? In other words since [12, 4] 12 is the highest value but how can i get '4'?
*note after sorting the arrays from the first val, i would need access to all the values.
That code only check the first value of the nested array. If it's fine to you, you have just to store the whole nested array, instead the first value. So:
var result = array.reduce(function(max, arr) {
return max[0] >= arr[0] ? max : arr;
});
Notice that I removed -Infinity, in that case the first iteration would start already with the first item of the array ([1, 5] in your case).
So now you can access to 12 using result[0] and 4 using result[1].
It sounds like you want to sort the list and grab the second item from the first result:
array.sort(function(a,b) {
return a[0] > b[0] ? -1 : 1
})[0][1]; -- 4
You can try the following:
array.reduce(function(max, arr) {
return max >= arr[0] ? max : arr[0];
});
Or you can use Math.max:
array.reduce(function(max, arr) {
return Math.max(max, arr[0]);
});

Categories