How to use javascript map to combine numbers at every nth element? - javascript

I like to combine numbers at every 4th index of an array. In the following oversimplified example, I did using "for" loop. Instead of that, I like to learn how to use "map" to achieve the same result. Thanks for any help!
function test() {
var array = [1, 2, 3, 4, 5, 6, 7, 8], arrayNew = [];
for (var n = 0; n < 4; ++n)
arrayNew[n] = array[n] + array[n + 4];
console.log(arrayNew)
}

To use .map, you could iterate the slice of the array that omits the first four elements. During that iteration, the loop index will be 4 units less, so you can grab array[i] and combine it with the currently iterated value from the slice:
const array = [1, 2, 3, 4, 5, 6, 7, 8];
const result = array.slice(4).map((val, i) => array[i] + val);
console.log(result);
If you want to add more than just two values, but want to also add the value at 2n, 3n, ...etc, then you need a nested loop. Here .map is of less use. I would "map" with the use of Array.from, which has a callback function that performs a mapping. Secondly, the sum that has a dynamic number of terms can be performed with reduce:
function accumulate(array, n) {
const groups = Array.from({length: array.length / n});
return Array.from({length: n}, (val, i) =>
groups.reduce((sum, _, j) => sum + array[i + j*n], 0)
);
}
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
console.log(accumulate(array, 4));

Related

Javascript get array element from the condition of summation of array element

I have an Array, arr = [2,4,8,7,3,6] I want to make each element of it be summation when the result is 10 , then save the element it would be arranged to another array.
make the element that result is 10 close each other like 2 and 8, add to another element named arr2.
result i need : arr2[2,8,3,7,4,6]
my code :
const arr = [2, 4, 8, 7, 3, 6];
let arr2 = [];
for (let i = 0; i < arr.length(); i++) {
let Number1 = arr[i];
let Number2 = arr[(i + 1)];
if (Number1 + Number2 === 10) {
let element1 = arr.indexOf(Number1);
let element2 = arr.indexOf(Number2);
arr2.push(element1, element2);
}
console.log(arr2[i]);
}
someone can solve my problem please ?
If you need to create arr2 so that the items sum up to 10 you can make use of a simple map here:
const arr = [2, 4, 8, 7, 3, 6];
const arr2 = arr.map((item) => 10 - item)
console.log(arr2);
You should first loop through the array to create a dictionary of value to index, then loop the array again and lookup for the complement of the current value to the target. If it exist then yes you got the answer.
.filter(x => x > i) is to search for complement that has higher index than current one so that we will not get duplicated result pushed. For example input is [2, 8], you don't want to get [2, 8, 8, 2]
Here is my solution
const arr = [2, 4, 8, 7, 3, 6];
let arr2 = [];
function solution(target: number, input: number[]): number[] {
const result: number[] = [];
const lookUpMap: {[key: number]: number[]} = {};
let i = 0;
for (const each of input) {
if (!(each in lookUpMap)) {
lookUpMap[each] = [];
}
lookUpMap[each].push(i);
i++;
}
i = 0;
for (const each of input) {
const difference = target - each;
if (difference in lookUpMap) {
const complementIndex = lookUpMap[difference].filter(x => x > i)[0];
if (complementIndex) {
result.push(input[i], input[complimentingIndex]);
}
}
i++;
}
return result;
}
arr2 = solution(10, arr);
console.log(arr2);
Assuming a valid result can be created for the given arr. A fairly simple solution would be to sort the array first. Then step through half the array and take the element on the current index, and the element on the inverse index (length - 1 - index). And push() those both in the resulting array.
So here in steps, given you have the following array:
[2, 4, 8, 7, 3, 6]
You sort it:
[2, 3, 4, 6, 7, 8]
Then you step through half the indexes and take each element, and the element on the inverse index.
[2, 3, 4, 6, 7, 8]
// \ \ \/ / /
// \ ------ / -> [2, 8, 3, 7, 4, 6]
// ----------
const arr = [2, 4, 8, 7, 3, 6];
const sortedArr = Array.from(arr).sort((a, b) => a - b); // ascending
const length = sortedArr.length;
const nPairs = length / 2;
const arr2 = [];
for (let i = 0; i < nPairs; ++i) {
arr2.push(
sortedArr[i],
sortedArr[length - 1 - i],
);
}
// or if you want a more functional approach:
// const arr2 = Array.from({ length: nPairs }).flatMap((_, i) => [sortedArr[i], sortedArr[length - 1 - i]]);
console.log(arr2);
Do note that this is probably not the fastest solution, because sorting is non-linear.
Obviously this solution does not work if an invalid input is given, like [7,2,1,8] which can never produce a valid output.

How to multiply elements of an array by elements from another array with the same index?

I am trying to write an JS algorithm in which I have two arrays.
The value of the first one will have different numerical values. The second array will be constant, say for example [5, 3, 6, 8].
Now I would like to multiply the values from the first array, by the corresponding index value from the second array, so having for example such a first array: [3, 7, 2, 5] it would look like this: 5*3, 3*7, 6*2, 8*5.
From the result I would like to create a new array, which in this case is [15, 21, 12, 40].
How can I achieve this result?
You can use map() and use the optional parameter index which is the index of the current element being processed in the array:
const arr1 = [3, 4, 5, 6];
const arr2 = [7, 8, 9, 10];
const mulArrays = (arr1, arr2) => {
return arr1.map((e, index) => e * arr2[index]);
}
console.log(mulArrays(arr1, arr2));
This is assuming both arrays are of the same length.
You can simply use for loop -
var arr1 = [5, 3, 6, 8];
var arr2 = [3, 7, 2, 5];
var finalArr = [];
for (var i = 0; i < arr1.length; i++) {
finalArr[i] = arr1[i] * arr2[i];
}
console.log(finalArr);

Update array of numbers so they are after each other

I have an array of numbers that a user can add and remove from a page. I need to arrange the numbers in the array so they are always after each other when a number is added/removed
const numbers = [1,2,3,4,5,6,7,8]
5 is removed from the array of how do I fix so the numbers are after each other e.g below
numbers need to be [1,2,3,4,5,6,7]
or if 2 is removed
numbers need to be [1,2,3,4,5,6,7]
Is there a way to fix this with lodash or es6?
After Removing the number from Array, you can iterate over it using for loop, and assign that index number to that position in array.
const numbers = [1,2,3,4,5,6,7,8]
numbers.splice(1, 1) //2 was removed
for(var i = 0; i < numbers.length; i++){
numbers[i] = i+1;
}
Here's how I would do it.
After you've removed the number, loop through the array and set the number to the index of the array.
Using .forEach()
const array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
addEventListener('click', _ => {
const removed = array.splice(Math.floor(Math.random() * array.length), 1);
array.forEach((_, i) => array[i] = i);
console.log(`Removed: `, removed[0]);
console.log(`New Array`, array);
});
Using .map()
let array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
addEventListener('click', _ => {
const removed = array.splice(Math.floor(Math.random() * array.length), 1);
array = array.map((_, i) => i);
console.log(`Removed: `, removed[0]);
console.log(`New Array`, array);
});

How to map only every second value in array

I have some array of numbers:
var arr = [1, 7, 1, 4];
I want to increase only every first value, such that the expected output would be: [2, 7, 2, 4]
I tried some combination of map and filter but I don't understand how it can work together...
var mapuj = arr.map(x => x *2);
You can use map() and use second argument which is idnex to determine if it's at event index or not
let arr = [1, 7, 1, 4];
let output = arr.map((n, index) => index % 2 === 0 ? n * 2 : n);
console.log(output);

Best algorithm to perform alternate sorting of array using javascript?

The following was my interview question. But I couldn't crack it and even could not think how to get this done.
var arr = [1,4,5,8,3,2,6,9,7,10];
Expected output of alternate sorting:
[10,1,9,2,8,3,7,4,6,5]
What I have tried:
I tried slicing out the Math.max.apply(null,arr) and Math.min.apply(null,arr) alternatively to push into separate empty array. But It was told that the algorithm is not optimal.
I would sort the array, and then iterate it, picking values from the begining and the end (inloop calculated offsets), in each iteration. A final check to odd arrays would complete the process.
let a = [1, 4, 5, 8, 3, 2, 6, 9, 7, 10];
a.sort((a, b) => a - b);
let b =[];
let l = a.length-1; // micro optimization
let L = l/2; // micro optimization
for(var i=0; i<L; i++) b.push( a[l-i] ,a[i] );
if(a.length%2) b.push( a[i] ); // add last item in odd arrays
console.log(b);
Result :
b =  [10, 1, 9, 2, 8, 3, 7, 4, 6, 5]
Algorithm bennefits:
Avoiding alterations in the original array (through pop and shift), improves the performance considerably.
Precalculating l and L before the loop , prevents the need of being calculated repeatedly in each iteration.
A single conditional cheking at the end of the procces, to handle odd arrays, slightly improves the speed.
I've prepared some PERFORMANCE TESTS, with some of the proposed algorithms :
Original Array(10 items) and Big Array(1000 items)
Here is one way to do it:
var arr = [1, 4, 5, 8, 3, 2, 6, 9, 7, 10];
// Sort the source array
arr.sort((a, b) => a - b);
// This will be the final result
var result = [];
// Create two pointers
var a = 0,
b = arr.length - 1;
while (result.length < arr.length) {
// Push the elements from start and end to the result array
result.push(arr[b]);
// Avoid bug when array is odd lengthed
if (a !== b) {
result.push(arr[a]);
}
a++;
b--;
}
console.log(result);
The idea is to have two pointers (a and b) traversing the the sorted original array from both the directions and appending the elements in result.
If you assume that the array will be a set of sequential numbers (a good question to ask about the data) you can do this very quickly with no need to sort or mutate the original array(i.e O(n)):
var arr = [1, 4, 5, 8, 3, 2, 6, 9, 7, 10];
let a = arr.reduce((a, c, i) => {
a[c > arr.length >> 1 ? (arr.length - c) << 1 : (c << 1) - 1] = c
return a
}, [])
console.log(a)
Here's my answer, based off the intuition that you're taking from the front then the back repeatedly from the sorted array until you're empty. The trick is avoiding "max" and "min" which evaluate the entire array, and just sorting it once.
Many of the other answers will put an undefined into the array if the original array has an odd length. I would leave a comment on those but I do not have the reputation. This is why I bounds check twice per loop.
var arr = [1,4,5,8,3,2,6,9,7,10];
// Sort numerically (not lexicographically)
arr.sort((a, b) => a - b)
// The output array
var out = []
// Take from the front, then back until original array is empty
while (true) {
if (arr.length == 0) break
out.push(arr.pop())
if (arr.length == 0) break
out.push(arr.shift())
}
// Output answer
console.log(out)
My solution for readability / no hidden magic:
// Input
var arr = [1,4,5,8,3,2,6,9,7,10];
// Sort
var arr1 = arr.sort((a,b) => (a - b));
// Compose
var arr2 = [];
for (var i = 0; i < arr1.length; i++) {
arr2.push(arr1[(i % 2) === 0
? arr1.length-1-(i/2) // get from end half
: (i-1)/2 // get from begin half
])
}
// Output
console.log(arr2); // = [10, 1, 9, 2, 8, 3, 7, 4, 6, 5]
Their interview answer "that the algorithm is not optimal." is not unexpected ofcourse. I would inquire why they say that, and ask if its really benefitial to spend dollar time on dimes here. (or tens of dollars on cents, actually)
Alternative method with only one variable to increment:
var arr = [1, 4, 5, 8, 3, 2, 6, 9, 7, 10];
arr = arr.sort((a, b) => b - a);
var result = [];
var a = 0;
while (result.length < arr.length) {
result.push(arr[a]);
result.push(arr[arr.length - a - 1]);
a++;
}
console.log(result);
var a = [1,4,5,8,3,2,6,9,7,10];
var b = a.sort((a, b) => a - b);
var c = a.sort((a, b) => a - b).reverse();
var d = [];
let e = a.length-1;
let f = e/2;
for(let i=0; i<f; i++) d.push( b.pop(), c.pop() );
Replace b and c in the for loop with functions to test:
for(let i=0; i<f; i++) d.push( a.sort((a, b) => a - b).pop(), a.sort((a, b) => a - b).reverse().pop() );
sort the array and divide into two parts , now use reduce to put elements from the two arrays
//original array
var arr = [1, 4, 5, 8, 3, 2, 6, 9, 7, 10];
//sorting origina array in ascending order
var m = arr.sort(function(a, b) {
return a - b;
});
// diving the sorted array in two parts
let getFirstSet = m.splice(0, arr.length / 2);
// now m containleft over items after the splice
// again sorted it in descending order to avoid back looping
let getSecondSet = m.sort(function(a, b) {
return b - a;
});
//using reduce function
let newArray = getFirstSet.reduce(function(acc, curr, index) {
// pushing element from second array containing 10,9,8,7,6
acc.push(getSecondSet[index]);
// pushing element from first array containing 1,2,3,4,5
acc.push(getFirstSet[index]);
return acc;
}, []); // [] is the initial array where elements will be pushed
console.log(newArray)
Another alternative view ... should this funky sort be done in place, like .sort is?
let input = [1, 4, 5, 8, 3, 2, 6, 9, 7, 10];
input.sort((a, b) => b - a).every((n, i, a) => (a.splice((i * 2 + 1), 0, a.pop()), (i * 2) < a.length));
console.log(input);
Here is a quick solution, using ternary operators and modulo operator for toggling.
let arr = [1, 4, 5, 8, 3, 2, 6, 9, 7, 10];
let j = 0;
let k = arr.length - 1;
// sort array
arr.sort((a, b) => a - b);
let new_array = [];
for (let i in arr) {
new_array[i] = i % 2 == 0 ? arr[k--] : arr[j++];
}
// prints array
console.log(new_array);

Categories

Resources