Find largest adjacent product in array (JavaScript) - javascript

I'm trying to understand the following solution for finding the largest adjacent product in any given array.
Example:
For inputArray = [3, 6, -2, -5, 7, 3], the output should be
adjacentElementsProduct(inputArray) = 21.
7 and 3 produce the largest product.
Possible solution in JS:
function adjacentElementsProduct(arr) {
return Math.max(...arr.slice(1).map((x,i)=>[x*arr[i]]))
}
I am having a hard time understanding two things:
What do the three dots exactly do and how does this get passed into the function? Is there any way to write this in a more understandable way? I know that is the "spread syntax" feature in ES6, but still don't understand completely.
Why do we insert "1" as argument to slice? My first though was to input "0", because we want to start at the start, then loop through everything, and see which adjacent product is the largest.
I'd appreciate any advice, links and explanations.
Thanks.
Cheers!

1. What do the three dots exactly do and how does this get passed into the function? Is there any way to write this in a more understandable way? I know that is some kind of "spread" feature in ES6, but still don't understand completely.
The Math#max needs a list of numbers as parameters, and map produces an array. The spread syntax is used to convert an array to be expanded to a list of parameters.
const arr = [1, 2, 3];
console.log('max on array', Math.max(arr));
console.log('max on list of parameters', Math.max(...arr));
In this case you can use Function#apply to convert the array to a list of parameters. I find it less readable, however.
const arr = [1, 2, 3];
console.log(Math.max.apply(Math, arr));
2. Why do we insert "1" as argument to slice? My first though was to input "0", because we want to start at the start, then loop through everything, and see which adjacent product is the largest.
Lets break down the iteration order of the 2 arrays.
[3, 6, -2, -5, 7, 3] // inputArray
[6, -2, -5, 7, 3] // inputArray.slice(1)
Now on each iteration of inputArray.slice(1):
x: 6, i = 0, arr[0] = 3
x: -2, i = 1, arr[1] = 6
x: -5, i = 2, arr[2] = -2
Since the inputArray.slice(1) array starts from the 2nd element of the inputArray, the index (i) points to the 1st element of the inputArray. And the result is an array of products of 2 adjacent numbers.

var biggestProduct = inputArray[0] * inputArray[1];
for (i=0; i<inputArray.length-1 ; ++i)
{
console.log(biggestProduct)
if ((inputArray[i] * inputArray[i+1] ) > biggestProduct)
{
biggestProduct = inputArray[i] * inputArray[i+1]
}
}
return biggestProduct;
Note: I've declared a variable that consists of 2 input arrays with index number then starts a for loop that indicates input array with his index number, so by that he will go throw all the index number of the array (one of them raised by one so that they won't be at the same value). and at the end of the code, you have the if statement.

You may simply do as follows;
function getNeigboringMaxProduct([x,...xs], r = -Infinity){
var p = x * xs[0];
return xs.length ? getNeigboringMaxProduct(xs, p > r ? p : r)
: r;
}
var arr = [3, 6, -2, -5, 7, 3],
res = getNeigboringMaxProduct(arr);
console.log(res);

Related

JAVASCRIPT REGEX for digits suite

Is there a way to use regex to check if an array contains exactly one occurence of each number in a range ?
myArr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
I have tried this :
let regex = /[1-9]{1}/;
But this only checks that the array contains at least one occurence in the range : )
The described validation is not a particularly good use case for regex.
One alternative way to find the answer you seek is to:
Create a Set with the array items. (A Set by default only retains unique values.)
Convert the Set back to array.
Compare the lengths of the original array and the new array. If they mismatch, the difference is the number of array items that exist in duplicate.
// return TRUE if myArr only has unique values
[...new Set(myArr)].length === myArr.length
You can just filter for duplicates and compare the original array with the filtered to see if it had any duplicates. Upside here is that you can use the filtered array if you need it
let myArr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 5]
let uniques = myArr.filter((v, i, a) => a.indexOf(v) === i)
let hasDupes = myArr.length != uniques.length
console.log("hasdupes?", hasDupes);
console.log(uniques)

group items in array in javascript

I have an array of items, can be objects with many properties, and I want to group some of these items based on order:
example:
[a,b,c,d,e] => [a,[b,c,d],e]
must group (b, c, d) or (a) or (b, c) or (all)
must not group (a, c) or (a, d) for example because they are not sequential
Some possibilites:
[a,b,c,d] to [[a,b,c,d]]
[a,b,c,d] to [[a],b,c,d]
[a,b,c,d] to [[a,b],c,d]
[a,b,c,d] to [[a,b,c],d]
[a,b,c,d] to [a,b,[c,d]]
always sequential items
think of item a like an object with index;
If I understand correctly, you want to group n sequential elements of the array starting from an index ind and put that that group back into the array at the same index. You can acheive that using splice:
function group(arr, ind, n) {
var g = arr.splice(ind, n); // cut out n elements from the array at index ind
arr.splice(ind, 0, g); // push back those cut-out elements into the same index ind (the elements are in array because of the first slpice call)
}
var arr = [1, 2, 3, 4, 5, 6];
group(arr, 2, 3);
console.log(arr); // [1, 2, [3, 4, 5], 6]
EDIT:
As requested, changing group to create a new array instead of altering the original and taking start and end indexes. So for that we are going to use slice/concat instead of splice:
function group(arr, start, end) {
return [].concat(arr.slice(0, start), [arr.slice(start, end + 1)], arr.slice(end + 1));
}
var arr = [1, 2, 3, 4, 5, 6];
console.log(group(arr, 2, 3)); // => [1, 2, [3, 4, 5], 6]
console.log(group(arr, 4, 6)); // => [1, 2, 3, 4, [5, 6]]
console.log(group(arr, 0, 3)); // => [[1, 2, 3, 4], 5, 6]
which concatinate the subarrays: from 0 to start, from start to end + 1 (put in an array of its own so its stays grouped) and from end + 1 onward. If you want the end index to be exclusive (the element at end not included) then just change end + 1 to end.
Based on the more recent comments you may be looking for Array's own, built-in slice method, it provides a continuous sub-region of an array, where start and end positions are its arguments:
function format(a){return "["+a.join(",")+"]";}
var arr=['a','b','c','d','e'];
console.log("original: "+format(arr));
console.log("slice(0,1): "+format(arr.slice(0,1)));
console.log("slice(0,2): "+format(arr.slice(0,2)));
console.log("slice(1,4): "+format(arr.slice(1,4)));
console.log("slice(2,4): "+format(arr.slice(2,4)));
console.log("slice(2,2): "+format(arr.slice(2,2)));
Note 1: The second argument is the position of the "last+1" element you want, it is best seen in the last example where slice(2,2) provides an empty array
Note 2: format is just about getting array contents in one line, console.log(somearray) displays the elements vertically.
Then of course you can do whatever you need, but it is definitely worth to note that this function exists and it is built-in.
Like building the array-in-array thing you describe:
function format(a){var s="[",first=true;a.forEach(function(i){
if(first)first=false;else s+=",";s+=i instanceof Array?format(i):i;});
s+="]";return s;}
function group(arr,begin,end){
var ret=[];
for(var i=0;i<begin;i++)ret.push(arr[i]);
ret.push(arr.slice(begin,end));
for(var i=end;i<arr.length;i++)ret.push(arr[i]);
return ret;
}
var arr=['a','b','c','d','e'];
console.log("original: "+format(arr));
console.log("group(arr,0,1): "+format(group(arr,0,1)));
console.log("group(arr,0,2): "+format(group(arr,0,2)));
console.log("group(arr,1,4): "+format(group(arr,1,4)));
console.log("group(arr,2,4): "+format(group(arr,2,4)));
console.log("group(arr,2,2): "+format(group(arr,2,2)));
Examples are the same as for the slice-explanation, including the empty array in the last one (with 2,2). It is up to you if you want such empty element (as kind of a 'cursor') or not.
And of course the thing also works with the nested loops in my original answer, if you want to generate all possible selections from an array - that is how your question initially seemed to me:
function format(a){var s="[",first=true;a.forEach(function(i){
if(first)first=false;else s+=",";s+=i instanceof Array?format(i):i;});
s+="]";return s;}
function group(arr,begin,end){
var ret=[];
for(var i=0;i<begin;i++)ret.push(arr[i]);
ret.push(arr.slice(begin,end));
for(var i=end;i<arr.length;i++)ret.push(arr[i]);
return ret;
}
var arr=['a','b','c','d','e'];
console.log("original: "+format(arr));
for(var i=0;i<arr.length;i++)
for(var j=i+1;j<=arr.length;j++){
console.log(format(group(arr,i,j)));
}

Newbie to Javascript: how to sum specific numbers in an array

Please help, I've been looking for an answer for far too long.
I'm trying to create an array using push method to insert the numbers
0 to 10 into positions 0 through 10 of the numbers array you just initialized above.
I did this:
var numbers = [];
for(var i = 0; i < 10; i++) {
numbers.push(i);
console.log(numbers);
And got this result, which I think is correct but not 100% sure:
[ 0 ]
[ 0, 1 ]
[ 0, 1, 2 ]
[ 0, 1, 2, 3 ]
[ 0, 1, 2, 3, 4 ]
[ 0, 1, 2, 3, 4, 5 ]
[ 0, 1, 2, 3, 4, 5, 6 ]
[ 0, 1, 2, 3, 4, 5, 6, 7 ]
[ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
0
Then I am to test the array push method by printing the sum of the values at
position 3 and 6 of the array (use the console.log() function to print to the console).
The outputted value should be 9.
I am so stuck on this point and cannot find a sample anywhere of how to accomplish this. I thought it might be something like:
console.log(numbers(sum[3, 6]);
If you want to have a sum() function, then try the following:
function sum(x, y) {
return x + y;
}
console.log(sum(numbers[3], numbers[6]));
Here's a Fiddle: https://jsfiddle.net/7181h1ok/
To sum the values of two indices of an array, you use the + addition operator in the following fashion:
var numbers = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
var sum = numbers[3] + numbers[6]; //adds the value in index 3 of the numbers array to the value in index 6 of the numbers array.
console.log(sum); //prints the sum to the console.
As a note, if you are unfamiliar with JavaScript and/or its operators, there's useful documentation at w3schools that can get you started.
First, let's convert your code to a little bit better style:
const numbers = [];
for (let i = 0; i < 10; i++) {
numbers.push(i);
console.log(numbers);
}
Note: I made numbers a const instead of a var, since you don't change it. I also made i a let binding instead of a var. In general, var is a legacy and should never be used. Use const instead if at all possible, otherwise use let.
Also, I inserted a space after the for keyword. It is generally recommended to separate the parentheses which enclose the header of a control structure keyword (if, while, for, etc.) with a space, to make it visually distinct from the parentheses for the argument list of a function call, which has no space.
Secondly: Your result is not correct. (Hint: how many numbers are the numbers 0 to 10?) It should include the numbers 0 to 10, but it only includes the numbers 0 to 9. You have what is generally called an off-by-one-error. These errors are very common when dealing with trying to manage loop indices manually. This is the fix:
const numbers = [];
for (let i = 0; i <= 10; i++) {
// ↑
numbers.push(i);
console.log(numbers);
}
Most modern programming languages have better alternatives than dealing with loop indices manually in the form of higher-level abstractions such as iterators, maps, and folds. Unfortunately, ECMAScript doesn't have a Range datatype, otherwise this could simply be expressed as converting a Range to an Array.
If ECMAScript did have a Range datatype, it could for example look like one of these:
const numbers = Range(0, 10).toArray()
const numbers = Array.from(Range(0, 10))
Here is an alternative for creating the numbers Array that doesn't involve manually managing loop indices, but still requires knowing that 0 to 10 are 11 numbers:
const numbers = Array.from({length: 11}, (_, i) => i)
If you want to add the numbers at indices 3 and 6, you can simply dereference indices 3 and 6 and add the results:
console.log(numbers[3] + numbers[6])
In the comments, you asked how you would add up all numbers in the Array. Combining the elements of a collection using a binary operator is called a fold or reduce, and ECMAScript supports it out-of-the-box:
console.log(numbers.reduce((acc, el) => acc + el));
Note how there is no explicit loop, thus no explicit management of loop indices. It is simply impossible to make an off-by-one-error here.
It will be: console.log((+numbers[3]) + (+numbers[6]));
Typically, it should be console.log(numbers[3] + numbers[6]); but there's sometimes a issue that results in 36 instead of 9. The extra + signs tell javascript that it is a number.
NOTE: Remember that the first number is numbers[0]. The array starts with 0!

Choose if array element repeats itself twice -- Javascript [duplicate]

This question already has answers here:
Get all non-unique values (i.e.: duplicate/more than one occurrence) in an array
(97 answers)
Closed 6 years ago.
There is a javascript array
var arr = [0, 1, 2, 2, 3, 3, 5];
I want to choose elements that repeats twice. In this case its 2 and 3. and i want attach them into a variable.
var a = 2, b = 3;
As far as i know there is no built-in function to do that job. How can i do that. Thanks.
You can use filter to get the values that occur twice.
var arr = [0, 1, 2, 2, 3, 3, 5];
var dups = arr.filter ( (v,i,a) => a.indexOf(v) < i );
console.log(dups);
In comments you stated you would only have doubles, but no values that occur more than twice. Note that the above would return a value more than once, if the latter would be the case.
This returns the values in an array, which is how you should work. To put them in separate values can be done as follows:
var [a, b, ...others] = dups;
...but you would have to know how many variables to reserve for that, and it does not make your further program any easier. JavaScript has many nice functions (methods) for arrays, so you should in fact leave them in an array.
There is no built in function to do that indeed.
You will have to loop thought the array and keeping track of the number of occurrences of the elements, while building a response array.
You could filter a sorted array.
var arr = [0, 1, 2, 2, 3, 3, 5],
repeats = arr.filter(function (a, i, aa) {
return aa[i - 1] === a;
});
console.log(repeats);
Most simple way to do this is the following:
var dups = [];
var arr = [0, 1, 2, 2, 3, 3, 5];
arr.forEach(function (v, i, a){
delete arr[i];
if (arr.indexOf(v) !== -1){
dups.push(v);
}
});
console.log(dups);
It's destructive however.

How to negate all elements in javascript array

What is the shortest way to negate all elements in a javascript array, with reasonable efficiency?
For example, the solution would convert [0, 18, -1, -2, 1, 3] to [0, -18, 1, 2, -1, -3]
The solution does not need to handle any values that are NaN/undefined/null, because the array I need this for does not contain any of those values.
Here is what I normally do (with array array):
for(var i = 0; i < array.length; i++) {
array[i]*=-1
}
The problem is that I need to invert this array in several places, so don't want to reuse large code.
Thanks
That would be array.map returning the negative of each value. Adding in arrow function for an even shorter syntax.
var negatedArray = array.map(value => -value);
negate all elements in a javascript array
I think you are referring to negate only the positive number.
var _myArray = [0, 18, -1, -2, 1, 3]
var _invArray = [];
_myArray.forEach(function(item){
item >0 ?(_invArray.push(item*(-1))) :(_invArray.push(item))
})
console.log(_invArray);
JSFIDDLE

Categories

Resources