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

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

Related

How do I group repeated integers from a 2d array in javascript

I have an array of 3 value arrays, and I need to convert them into a set of arrays where each array is made up of the values which were common between arrays, so my input of
[[2,3,9], [1,4,7], [3,6,9], [1,7,5], [7,5,8], [9,6,10], [3,6,10], [1,8,5]]
becomes
[[2,3,6,9,10],[1,4,5,7,8]]
Order is not important. I've found similar questions such as Group same values in an array within an array in JS but it seems slightly different to my case, but I imagine using reduce is the way to go, but I don't entirely understand how. I have tried creating an object using the following format, but couldn't get from there to an answer:
{
vertex: 3,
triangles: [2,3,9], [3,6,9], [3,6,10]
}
Here is one algorithm. Take first item from array and check first item array has any common array. If they have common item, then merge it and move the merged array to first item of array. If no common item, then add to result array.
const merge = (arr) => {
const result = [];
while (arr.length > 0) {
let first = arr.shift();
const idx = arr.findIndex((items) =>
items.some((item) => first.includes(item))
);
if (idx !== -1) {
first = first.concat(arr[idx]);
arr.splice(idx, 1);
arr.unshift(first);
} else {
result.push(first);
}
}
return result.map(items => [...new Set(items)]);
};
const data = [
[2, 3, 9],
[1, 4, 7],
[3, 6, 9],
[1, 7, 5],
[7, 5, 8],
[9, 6, 10],
[3, 6, 10],
[1, 8, 5],
];
console.log(merge(data));

Sum the value of array elements with the previous element(s)

I need a hand to sum the value of array elements with the previous element(s) and return a new array.
So if we have :
let durations = [4, 3.5, 6];
then in the new array the first element is 4, the second element would be the sum of 4 + 3.5 and the third one would be 4 + 3.5 + 6; so the desired result would be [4, 7.5, 13.5]
So far it seems that reduce unexpectedly just concat the numbers and returns an array of strings !!!
let durations = [4, 3.5, 6];
let arr = [];
let durationsNew = durations.reduce((a, b) => {
arr.push(a + b);
return arr;
}, []);
console.log(durationsNew); // The desired result is [4, 7.5, 13.5]
In your code, you take the accumulator a and add the value to it. The accumulator is an array and this is converted to string by using it with a plus operator.
Instead, you could take a variable for sum and map the sum by adding the value for each element.
let durations = [4, 3.5, 6],
sum = 0,
array = durations.map(value => sum += value)
console.log(array); // [4, 7.5, 13.5]
Try this - a mixture of map() and reduce():
[4, 3.5, 6].map((num, i, arr) =>
num + arr.slice(0, i).reduce((a, b) =>
a + b, 0)); //[4, 7.5, 13.5]
The idea is to map the array to a new array, and for each number, the new number returned is the number + the sum of the array values up to that number.
If you are going to use reduce, you have to do something like this:
let durations = [4, 3.5, 6]
let durationsNew = durations.reduce((_durationsNew, duration, durationIndex) => {
if(durationIndex > 0) {
_durationsNew.push(_durationsNew[durationIndex - 1] + duration)
} else {
_durationsNew.push(duration)
}
return _durationsNew;
}, [])
console.log(durationsNew); // The desired result is [4, 7.5, 13.5]
Example: https://repl.it/repls/HandsomeVacantRate
Benchmark test with Array.map, Array.reduce, and for loop:

Get values from array of arrays using push

I want to get values from an array of arrays, and I'm having difficulties doing it.
I have the following:
var id = 1; //value I want to use for the search
var _restrictions = [[1, 2], [2, 4], [5, 1], [1, 6]]; //arrays that I want to check
var arrVal = [];
By using the id, I want to retrieve all of the values, inside the arrays, where the id exits and store them in the array "arrVal".
For example:
_restrictions = [[1, 2], [2, 4], [5, 1], [1, 6]];
//arrVal will be: [2, 5, 6], because the id existing inside the arrays [1,2],
//[5,1] and [1,6]
The "_restrictions" array is a array of arrays that contain restrictions. They are independent values (the first one isn't the index or id).
How can I do that?
Thanks in advance!
Here's a version that will work for any size of nested array. It returns an flattened array of all values not including the id.
var id = 1;
var _restrictions = [[1, 2, 9], [2, 4], [5, 1], [1, 6]];
var arrVal = _restrictions.reduce((acc, c) => {
// Find the index of the id in each nested array
const i = c.findIndex(arr => arr === id);
// If it exists, splice it out and add it
// to the accumulator array
if (i > -1) {
c.splice(i, 1);
acc.push(...c);
}
return acc;
}, []);
console.log(arrVal);
EDIT: Updated code after the question is edited.
The question lacks a bit of clarity. I am assuming you want to filter the sub-arrays which have id in them i.e. contains the value 1.
let id = 1; //value I want to use for the search
let _restrictions = [[1, 2], [2, 4], [5, 1], [1, 6]];
let arrVal = _restrictions.filter((item) => {
return item.includes(id);
});
let new_array = arrVal.concat.apply([], arrVal).filter(x => x !== id);
console.log(new_array);
// [2, 5, 6]

Mapping array into array of tuples using LoDash

I've got an array such as:
var foo = [1, 2, 3, 4, 5];
and I would like to map it to:
var bar = [[1,2], [2,3], [3,4], [4,5], [5,1]];
I do not need to handle scenarios where the length of foo is 0 or 1.
My naive approach is:
var foo = [1, 2, 3, 4, 5];
var bar = _.map(foo, function(value, index) {
return index < foo.length - 1 ? [value, foo[index + 1]] : [value, foo[0]];
});
console.log(bar);
<script src="https://cdn.jsdelivr.net/lodash/3.10.1/lodash.js"></script>
I'm wondering if there's a more clear way to express this mapping.
Using plain simple lodash. First drop the first element from the array, append it, and then zip it with the original array:
var a = [1,2,3,4,5]
var b = _.zip(a, _.concat(_.drop(a), a[0]))
The result:
console.log(b)
[[1, 2], [2, 3], [3, 4], [4, 5], [5, 1]]
_.nth
Gets the element at index n of array. If n is negative, the nth element from the end is returned.
just get sibling in reverse order
var bar = _.map(foo, function(val, index) {
return [val, _.nth(foo, (index + 1) - foo.length)];
});

Flattening an array recursively (withoout looping) javascript

I'm practicing recursion and am trying to flatten an array without looping (recursion only). As a first step I did the iterative approach and it worked, but am stuck on the pure recursion version:
function flattenRecursive(arr) {
if (arr.length === 1) {
return arr;
}
return Array.isArray(arr) ? arr = arr.concat(flattenRecursive(arr)) : flattenRecursive(arr.slice(1))
}
console.log(flattenRecursive([
[2, 7],
[8, 3],
[1, 4], 7
])) //should return [2,7,8,3,1,4,7] but isn't - maximum call stack error
//working version (thanks #Dave!):
function flattenRecursive(arr) {
if (arr.length === 1) {
return arr;
}
return arr[0].concat(Array.isArray(arr) ? flattenRecursive(arr.slice(1)) : arr);
}
console.log(flattenRecursive([
[2, 7],
[8, 3],
[1, 4], 7
]))
//returns [ 2, 7, 8, 3, 1, 4, 7 ]
Here's a working version that's slightly less verbose.
//using reduce
function flattenRecursive(arr) {
return arr.reduce(function(result, a){
return result.concat(Array.isArray(a) ? flattenRecursive(a) : a);
}, []);
}
//without reduce
function flattenRecursive2(arr) {
if (arr.length === 0)
return arr;
var head = arr.shift();
if (Array.isArray(head))
return flattenRecursive2(head).concat(flattenRecursive2(arr));
else
return [head].concat(flattenRecursive2(arr));
}
var testArray = [1,[2, 3],[[4, 5, [6, 7]], [8, 9]], 10];
console.log(flattenRecursive(testArray));
console.log(flattenRecursive2(testArray));
<script src="http://gh-canon.github.io/stack-snippet-console/console.min.js"></script>
Sorry, I do not have the reputation to comment. Here are my 2 cents.
1) be careful about your initial condition. Here, it seems that if your input is ̀€arr = [[1,2]], your function returns [[1,2]], while you would like it to return [1,2].
2) in the core of the recursion, you must be sure than you recursively call your function with a smaller argument. Here, you should concat the first element of your array with the flattened rest of the array. The functionslice` may be handy for that.
3) It would be also be possible to use a reduce-like function.

Categories