How to find a max value for any quantity of arrays? - javascript

I need to find Max values for any number of arrays within the function. For example, user can add 1 array or 10 arrays. Output should show max values for each of the arrays.
Currently, my code works only if 1 array is provided.
Please let me know what is wrong.
function getMaxs(args){
array = args;
var max = array[0];
for(i = 0; i < array.length; i++){
if(max < array[i]){
max = array[i];
}
}
console.log(max);
return max;
}
getMaxs([5, 6, 7], [18, 19, 20], [5, 7, 3, 10]); // output is 7
getMaxs([5, 6, 7]); // output is 7
getMaxs([18, 19, 20], [5, 10, 74, 394]); // output is 20

If you need a max for every provided array:
const getMaxs = (...args) => args.map(arr => Math.max(...arr));
console.log( getMaxs([5, 6, 7], [18, 19, 20], [5, 7, 3, 10]) ); // [7, 20, 10]
console.log( getMaxs([5, 6, 7]) ); // [7]
console.log( getMaxs([18, 19, 20], [5, 10, 74, 394]) ); // [20, 394]

If you don't care which sub-array the result comes from, you can use Array.prototype.flat:
function getMaxs(array) {
const flatArray = array.flat();
return Math.max(...flatArray);
}
const arr = [[5, 6, 7], [18, 19, 20], [5, 7, 3, 10]];
const max = getMaxs(arr);
console.log(max);

I believe you're looking for rest parameters.
Something along these lines:
function getMaxs(...arrays) {
return Math.max(...arrays.flat());
}
// usage
getMaxs([5, 6, 7], [18, 19, 20], [5, 7, 3, 10]); // output is 20
getMaxs([5, 6, 7]); // output is 7
getMaxs([18, 19, 20], [5, 10, 74, 394]); // output is 394
Related: The arguments object in case you can't use rest parameters. In that case, you probably don't support flat either, which in that case I'll recommend you to look for a polyfill somewhere.

You can use the .flat() function, so the arrays would merge and become one, like this:
function getMaxs(args){
array = args.flat();
//it will now see it as one big array
....
}
But, the .flat() function may not work on older browsers, so you may also do this:
array = args.reduce((acc, val) => acc.concat(val), [])
The effect will be the same.

Iraklis solution is fine, but it suppose you give an array of arrays. However, if you want to pass arrays as separated arguments, you could use the Spread syntax and Rest parameters:
function getMaxs(...arrays) {
const max = Math.max(...arrays.flat())
console.log(max) // DEBUG
return max
}
getMaxs([5, 6, 7], [18, 19, 20], [5, 7, 3, 10])
getMaxs([5, 6, 7])
getMaxs([18, 19, 20], [5, 10, 74, 394])
Of course, you should be careful about browser compatibility:

function getMaxs(...args) {
array = args.flat();
var max = array[0];
for (i = 0; i < array.length; i++) {
if (max < array[i]) {
max = array[i];
}
}
// console.log(max);
return max;
}
console.log(getMaxs([5, 6, 7], [18, 19, 20], [5, 7, 3, 10]));
console.log(getMaxs([5, 6, 7]));
console.log(getMaxs([18, 19, 20], [5, 10, 74, 394]));
the above one will be the solution for your question. You can check the below screenshots for your reference.
For this input i have added screen shots for your reference how it will process the code
getMaxs([5, 6, 7], [18, 19, 20], [5, 7, 3, 10])
now it will take the whole
[![enter image description here][1]][1]

Related

How to retrieve sub array elements when they fulfill the the condition and stop the loop

const winningTemplate = {
firstRow: [0, 1, 2, 3, 4],
secondRow: [5, 6, 7, 8, 9],
thirdRow: [10, 11, 13, 14],
fourthRow: [15, 16, 17, 18, 19],
lastRow: [20, 21, 22, 23, 24],
firstDiagonal: [0, 6, 18, 24],
firstColumn: [0, 5, 10, 15, 20],
secondColumn: [1, 6, 11, 16, 21],
thirdColumn: [2, 7, 17, 22],
fourthColumn: [3, 8, 13, 18, 23],
lastColumn: [4, 9, 14, 19, 24],
lastDiagonal: [4, 8, 16, 20],
}
export default winningTemplate;
let checkTemplate = Object.values(winningTemplate)
let isWinner = 0
for (let checkWinner of checkTemplate) {
for (let checkMatchedBird of checkWinner) {
const newWinnerMatchedArray =
updatedBirdClonePlayerOne[checkMatchedBird]
console.log('newWinnerMatchedArray', newWinnerMatchedArray)
if (newWinnerMatchedArray.includes('match')) {
break
}
// setWinner('wins')
}
// break;
}
I am expecting that any of the row column and diagonal elements are matched with using includes('match') then declare the winner.
every time the code executes the condition ('match') fulfills,and I see the array newWinnerMatchedArray has matched elements -which is going fine till now.
Now I want that anytime when 5 elements of any row or col or 4 elements of any diagonal array are matched we declare a winner and the loop stops. I hope it is cleared
You can label the loop and break that specific loop:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label
loop1:
for (let i = 0; i < 5; i++) {
for(x of something) {
if (i === 1) {
break loop1;
}
}
str = str + i;
}
That being said I'd suggest simplifying your logic into pure functions and use the following:
forEach
map
reduce
some
every
These methods are more explicit about intention per line, and make it easier to read and manage. You can still obtain optimum performance in the algorhithm if you use them cleverly.

How to return the correct array which include all values inside the second array

Let say there are two array.
let MotherArray = [
[30, 1, 2, 3, 4, 5, 6],
[5, 6, 7, 8, 9],
[7, 8, 9],
];
let arraytoTest = [5,6];
What i want is that i want to return the array if
all the value inside the arraytoTest is included in the MotherArray[i]
I have tried
let MotherArray = [[30, 1, 2, 3, 4, 5, 6],[5, 6, 7, 8, 9],[7, 8, 9],];
let arraytoTest = [5, 6];
let result = MotherArray.includes(arraytoTest)
console.log(result);
But i don't think this is the correct method.
I also find the array.every() but i think my usage is not correct.
What I want is that I want to return MotherArray[0],MotherArray[1] which are [[30, 1, 2, 3, 4, 5, 6],[5, 6, 7, 8, 9]] in this particular example
since 5 and 6 are includes inside these 2 arrays.
You can combine array.filter() with array.every()
let MotherArray = [
[30, 1, 2, 3, 4, 5, 6],
[5, 6, 7, 8, 9],
[7, 8, 9],
];
let arraytoTest = [5,6];
let found = MotherArray.filter(childArray => arraytoTest.every(num => childArray.includes(num)));
console.log(found);
I think this is what you want; A combination of filter on the mother array and every for array you're testing.
let MotherArray = [
[30, 1, 2, 3, 4, 5, 6],
[5, 6, 7, 8, 9],
[7, 8, 9],
];
let arraytoTest = [5,6];
let result = MotherArray.filter(arr => arraytoTest.every(x => arr.indexOf(x)>-1));
console.log(result);
You can use filter and every like below.
Or you can use filter and some with negative condition like filter(x => !arraytoTest.some(y => !x.includes(y))). I think with some it would be efficient because
The some() method executes the callback function once for each element present in the array until it finds the one where callback returns a truthy value.
let MotherArray = [
[30, 1, 2, 3, 4, 5, 6],
[5, 6, 7, 8, 9],
[7, 8, 9],
];
let arraytoTest = [5,6];
let result = MotherArray.filter(x => arraytoTest.every(y => x.includes(y)));
console.log(result);
let result2 = MotherArray.filter(x => !arraytoTest.some(y => !x.includes(y)));
console.log(result2);

Filtering an array of arrays JS

I'm trying to write a function, that accepts an array of arrays as argument and filtering this array under certain condition. I will explain this condition later.
For example I have such array:
const arr = [
[1, 1, 20],
[2, 1, 15],
[3, 1.5, 15],
[4, 1, 15],
[5, 1, 20],
[6, 1.5, 15],
[7, 1, 25],
[8, 1, 15],
[9, 0, 15],
[10, 0, 15],
[11, 0, 15],
]
and the condition. I want to filter it by the value of the third column, but only if it's at least three in a sequence. The function should accept two arguments (or more if needed): value and array
So for example
const filterByValue = (array, val) => { //definition
return filtredArr
}
const newArr = filterByValue(array,15)
and now newArr should equal:
[
[2, 1, 15],
[3, 1.5, 15],
[4, 1, 15],
[8, 1, 15],
[9, 0, 15],
[10, 0, 15],
[11, 0, 15],
]
For now I only made:
const filterByValue = (arr, value) => {
const newArr = arr.filter((elem, index) => elem[2] === value)
return newArr
}
but this function returns
[
[2, 1, 15],
[3, 1.5, 15],
[4, 1, 15],
[6, 1.5, 15],
[8, 1, 15],
[9, 0, 15],
[10, 0, 15],
[11, 0, 15],
]
there shouldn't be [6,1.5,15]. I have no idea how it could be done to return only fragments of an array that contain at least three internal arrays in a row. Maybe any of you have any idea?
edit more explanation
This sequence means to me that I want only output which internal arrays that contain a set value in the third value (value argument in a function), but that they also have internal arrays that follow each other (at least three). Let's assume that the function accepts arr (first array in my post) and value = 15. The first internal array contains 20 as the third value, so it falls off. The second is okey, the third also and the fourth also - and should return in this situation 2,3,4 internal board (because they follow three in succession). Then the fifth value is 20, the sixth value is 15, but the next (seventh) value 25 again, so the function should not take into account the sixth table (because it is not followed by at least two tables that have the value 15). In the table 8,9,10,11 we have the value 15, and these are four tables (i.e. at least three). Therefore, the function should return an array containing the following tables 2,3,4 and 8,9,10,11. The sixth array contains the value 15, but not followed by two more that would have this value as well. The expected output is the second board in my post.
const filterByValue = (arr,value) => {
let newArray = [];
let cache = [];
arr.forEach(elem => {
if (elem[2] === value) {
cache.push(elem);
} else {
if (cache.length >= 3) {
newArray = newArray.concat(cache);
}
cache = [];
}
});
if (cache.length >= 3) {
newArray = newArray.concat(cache);
}
return newArray;
}
You could take a closure over an index and check if the values are in a sequence of three.
const
array = [[1, 1, 20], [2, 1, 15], [3, 1.5, 15], [4, 1, 15], [5, 1, 20], [6, 1.5, 15], [7, 1, 25], [8, 1, 15], [9, 0, 15], [10, 0, 15], [11, 0, 15]],
value = 15,
result = array.filter(
(index => ({ 2: v }, i, a) => {
if (v !== value) return false;
if (index === i || a[i + 1][2] === value && a[i + 2][2] === value) {
index = i + 1;
return true;
}
})
(-1)
);
console.log(result);
Try with filter and conditions based on whether match the value or not.
const arr = [
[1, 1, 20],
[2, 1, 15],
[3, 1.5, 15],
[4, 1, 15],
[5, 1, 20],
[6, 1.5, 15],
[7, 1, 25],
[8, 1, 15],
[9, 0, 15],
[10, 0, 15],
[11, 0, 15],
];
const filterByValue = (array, val) =>
array.filter((ar, i, items) => {
if (ar[2] !== val) {
return true;
} else {
return items[i - 1][2] === val || items[i + 1][2] === val;
}
});
console.log(filterByValue(arr, 15));
Without using the cache array.
Check if element contains number 15 if yes increment the counter if that counter reaches at least 3 it means you can store those 3 element into a new list. Use the the difference between the current index and the counter to get from the first sequence element to the last one. Repeat the process until end of the array is reached.
const arr = [
[1, 1, 20],
[2, 1, 15],
[3, 1.5, 15],
[4, 1, 15],
[5, 1, 20],
[6, 1.5, 15],
[7, 1, 25],
[8, 1, 15],
[9, 0, 15],
[10, 0, 15],
[11, 0, 15]
];
let cnt = 0;
let list = [];
for (let i = 0; i < arr.length; i++) {
// check if elements meet criteria
while (i < arr.length && arr[i][arr[i].length - 1] === 15) {
++i;
++cnt;
}
// acumulate into your array if at least 3 elm
if (cnt >= 3) {
for (let j = i - cnt; j < i; j++) {
list.push(arr[j]);
}
}
cnt = 0;
}
console.log(list)

To create a one-dimensional array which contains, in order, the array indices used to access a number in the given variable

//I am trying to learn/understand to create a one-dimensional array which contains, in exact order, the array indices used to access a given number within a multi dimensional array
var multiDimensionalArray = [1, 2, 3, [4, 5, 6, [7, 8, 9, [10, 11, 12, [13, 14, [15]]]]]];
// to access 15...
fifteen = multiDimensionalArray[3][3][3][3][2][0];
// Define the variable 'indexArray' here:
indexArray = fifteen.join();
//join method does not work for me. I have tried concat, slice, indexOf methods. Can't seem to be able to find the solution for this part. HELP!
// This will log your variables to the console
console.log(fifteen); //15
console.log(indexArray); //[3, 3, 3, 3, 2, 0]
You can use a recursive function :
var multiDimensionalArray = [1, 2, 3, [4, 5, 6, [7, 8, 9, [10, 11, 12, [13, 14, [15]]]]]];
const getIndex = (arr, num) => {
const path = [];
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
path.push(i);
path.push(getIndex(arr[i], num));
break;
}
if (arr[i] === num) {
path.push(i);
break;
}
}
return path.flat();
};
const indexArray = getIndex(multiDimensionalArray, 15);
console.log(indexArray);
Another approach with a recursive function:
var multiDimensionalArray = [1, 2, 3, [4, 5, 6, [7, 8, 9, [10, 11, 12, [13, 14, [15]]]]]];
const find = (node, needle) => {
const index = node.indexOf(needle);
const nextIndex = node.findIndex(Array.isArray);
return [].concat(...
(index !== -1)
? [index]
: [nextIndex, find(node[nextIndex], needle)]
);
};
const result = find(multiDimensionalArray, 15);
console.log(result);
You could take a recursive approach and return either an empty array fro a not found value or the indices.
function getIndices(array, value) {
var subIndices = [],
index = array.findIndex(v => v === value || Array.isArray(v) && (subIndices = getIndices(v, value)).length);
return index === -1
? []
: [index, ...subIndices];
}
var array = [1, 2, 3, [4, 5, 6, [7, 8, 9, [10, 11, 12, [13, 14, [15]]]]]]
console.log(getIndices(array, 15));
console.log(getIndices(array, 42));

Get some set of array based on condition from two arrays of array in Javascript

I have two arrays of array in Javascript like
var array1 = [[10, 2], [11, 4], [12, 30], [13, 17], [14, 28]];
var array2 = [[8, 13], [9, 19], [10, 6], [11, 7], [12, 1]];
I want to get the set of arrays from array1 which match the first element of each array of the array2
in my example case both array1 and array2 have array with first element as 10 11 and 12, so it should return
[[10, 2], [11, 4], [12, 30]];
is there any easy and efficient way using pure javscript or lodash, underscor framework or something like that. Without iterate over and match one by one of this two array ?
In ES6, you could use Set.
var array1 = [[10, 2], [11, 4], [12, 30], [13, 17], [14, 28]],
array2 = [[8, 13], [9, 19], [10, 6], [11, 7], [12, 1]],
set = new Set(array2.map(a => a[0])),
result = array1.filter(a => set.has(a[0]));
console.log(result);
Version with an object as hash table
var array1 = [[10, 2], [11, 4], [12, 30], [13, 17], [14, 28]],
array2 = [[8, 13], [9, 19], [10, 6], [11, 7], [12, 1]],
result = array1.filter(function (a) {
return this[a[0]];
}, array2.reduce(function (r, a) {
r[a[0]] = true;
return r;
}, Object.create(null)));
console.log(result);
You can use lodash _.intersectWith function in order to solve this problem in an inline.
_.intersectionWith(array1, array2, function(a, b) {
return a[0] === b[0];
});
I don't know about performance cos I haven't had the chance to have a look at the source code of this function. Anyway, I like it for its simplicity. Here's the fiddle in case you want to check it out.
If you can make use of Set, then you can compute the a set of numbers to look for first and use .filter to only get the arrays whose first element is in that set:
var haystack = new Set(array2.map(x => x[0]));
var newArray = array1.filter(x => haystack.has(x[0]));
Of course you can also use the lodash or underscore versions of .map and .filter.
Alternatives to using Set would be:
Create an array of numbers instead and use indexOf to test existence. That will scale linearly with the number of elements:
var haystack = array2.map(x => x[0]);
var newArray = array1.filter(x => haystack.indexOf(x[0]) > -1);
Create an object with number -> true entries to test existence with in, hasOwnProperty or just object access:
var haystack = array2.reduce((obj, x) => (obj[x[0]] = true, obj), {});
var newArray = array1.filter(x => haystack[x[0]]);
Which one performs better depends on the number of elements you have and the environment the code is running in.
You can do this with filter() and find()
var array1 = [
[10, 2],
[11, 4],
[12, 30],
[13, 17],
[14, 28]
];
var array2 = [
[8, 13],
[9, 19],
[10, 6],
[11, 7],
[12, 1]
];
var result = array1.filter(function(ar) {
return array2.find(function(e) {
return e[0] == ar[0]
})
})
console.log(result)
I would do this with a Map anf filter combo in ES6 as follows;
var array1 = [[10, 2], [11, 4], [12, 30], [13, 17], [14, 28]],
array2 = [[8, 13], [9, 19], [10, 6], [11, 7], [12, 1]],
m = new Map(array2),
array3 = array1.filter(a => m.has(a[0]));
console.log(array3);
If you need backwards compatibility other answers are pretty good.

Categories

Resources