Capture multiple values for ES6 array's map function - javascript

I want to perform an operation involving the current and the next array element.
For example, add current element with the next:
let arr = [0,1,2,3,4,5];
let newarr = arr.map((a,b) => a+b); //here, a and b are treated as the same element
expecting it to yield a new array of sums of current and next array element:
[0+1, 1+2, 2+3, 3+4, 4+5]
Is it possible to do that with map? If not, is there any other method that is suitable for manipulating multiple array elements in one operation?

here, a and b are treated as the same element
No. a is the value and b is the index. They happen to be the same in your particular data set.
Is it possible to do that with map?
Not with map itself. That will give you a new value for each value in the array, but you are starting with 6 values and ending up with 5, so you need an additional transformation.
Obviously you also need to use "the next value" instead of "the current index" too.
const arr = [0,1,2,3,4,5];
const newarr = arr.map((value, index, array) => value + array[index + 1]);
newarr.pop(); // Discard the last value (5 + undefined);
console.log(newarr);

You could slice the array and map with the value and value at same index of original array.
const
array = [0, 1, 2, 3, 4, 5],
result = array.slice(1).map((v, i) => array[i] + v);
console.log(result);

The second parameter in map is the index. Since map returns results for each iteration you can filter the unwanted item from the new array:
let arr = [0,1,2,3,4,5];
let newarr = arr.map((a,b) => a+arr[b+1]).filter(i => !isNaN(i));
console.log(newarr);

You can use reduce for that:
const arr = [0, 1, 2, 3, 4, 5];
const out = arr.reduce((acc, el, i) => {
if (i === arr.length - 1) { // don't do anything for the last element
return acc;
}
acc.push(el + arr[i + 1]);
return acc;
}, []);
console.log(out)

Using Array.prototype.slice(), Array.prototype.forEach().
const data = [0, 1, 2, 3, 4, 5],
numbers = data.slice(0, -1),
result = [];
numbers.forEach((number, index) => {
result.push(number + data[index + 1]);
});
console.log(result);

Related

In Javascript how do I create a secondary array in a specific index?

How do I create a subarray from an existing array in Javascript?
For example;
Arr = [5,2,1,2]
Then I want to insert 8 in position 1 of Arr, but keep the original value 2. So arr can become:
Arr = [5,[2,8],1,2]
I tried using concat, which sort of did something but duplicates all values.
Bear in mind that this can grow e.g. Arr = [5,[2,8,3,4],1,[2,3]]
Thanks!
You could assign the concatinated values.
const
addAt = (array, value, index) => array[index] = [].concat(array[index], value),
array = [5, 2, 1, 2];
addAt(array, 8, 1);
console.log(array)
addAt(array, 3, 1);
console.log(array)
.as-console-wrapper { max-height: 100% !important; top: 0; }
There are several different ways to do this, but you can reassign the current array index to an array like so:
Arr[1] = [Arr[1], 8]. Then if you wanted to continue adding to the array at index 1 in Arr, you could do something like Arr[1].push(x).
You could do something like this (Probably not the best answer, but may be helpful)
const addIntoArray = (arr, toAdd, index) => {
arr[index] = typeof arr[index] == "number" ? [arr[index], toAdd] : [...arr[index], toAdd];
return arr
}
Arr = [5,2,1,2]
console.log(Arr); // [ 5, 2, 1, 2 ]
addIntoArray(Arr, 1, 1)
console.log(Arr); // [ 5, [ 2, 1 ], 1, 2 ]
addIntoArray(Arr, 3, 1)
console.log(Arr) // [ 5, [ 2, 1, 3 ], 1, 2 ]
Basically ...arr expands the array and then we add toAdd at it's end and [arr[index], toAdd] creates an array with the first element as the number and the second the new element. (It modifies the original array, as shown in the example, so pay attention as it may lead to bugs)
The typeof arr[index] == "number"is just a simple/generic typecheck to see if there isn't an array already
This function should satisfy your conditions at basic level
// a - array, v - value to insert, i - position to insert
const avi = (a, v, i) => {
r = a.slice(0, i);
r.push([a[i], v]);
a.slice(i+1, a.length).forEach(e => r.push(e));
return r;
}
console.log(JSON.stringify(avi([5,2,1,2], 8, 1)))
//=> "[5,[2,8],1,2]"

Find indices of all duplicate records in js

Suppose I have an array as below:
Arr1 = [12,30,30,60,11,12,30]
I need to find index of elements which are repeated in array e.g.
ans: 0,1,2,5,6
I've tried this code but it is considering just single element to check duplicates.
First get all the duplicates using filter() and then using reduce() get he indexes of only those elements of array which are in dups
const arr = [12,30,30,60,11,12,30];
const dups = arr.filter(x => arr.indexOf(x) !== arr.lastIndexOf(x));
const res = arr.reduce((ac, a, i) => {
if(dups.includes(a)){
ac.push(i)
}
return ac;
}, []);
console.log(res)
The time complexity of above algorithm is O(n^2). If you want O(n) you can use below way
const arr = [12,30,30,60,11,12,30];
const dups = arr.reduce((ac, a) => (ac[a] = (ac[a] || 0) + 1, ac), {})
const res = arr.reduce((ac, a, i) => {
if(dups[a] !== 1){
ac.push(i)
}
return ac;
}, []);
console.log(res)
You could use simple indexOf and the loop to get the duplicate indexes.
let arr = [12,30,30,60,11,12,30]
let duplicate = new Set();
for(let i = 0; i < arr.length; i++){
let index = arr.indexOf(arr[i], i + 1);
if(index != -1) {
duplicate.add(i);
duplicate.add(index);
}
}
console.log(Array.from(duplicate).sort().toString());
A slightly different approach with an object as closure for seen items which holds an array of index and the first array, in which later comes the index and a necessary flattening of the values.
This answer is based on the question how is it possible to insert a value into an already mapped value.
This is only possible by using an object reference which is saved at the moment where a value appears and which is not seen before.
Example of unfinished result
[
[0],
[1],
2,
[],
[],
5,
6
]
The final Array#flat removes the covering array and shows only the index, or nothing, if the array remains empty.
[0, 1, 2, 5, 6]
var array = [12, 30, 30, 60, 11, 12, 30],
indices = array
.map((o => (v, i) => {
if (o[v]) { // if is duplicate
o[v][1][0] = o[v][0]; // take the first index as well
return i; // return index
}
o[v] = [i, []]; // save index
return o[v][1]; // return empty array
})({}))
.flat() // remove [] and move values out of array
console.log(indices);
You could use Array#reduce method
loop the array with reduce.At the time find the index of argument
And check the arguments exist more than one in the array using Array#filter
Finaly push the index value to new accumulator array.If the index value already exist in accumalator.Then pass the currentIndex curInd of the array to accumulator
const arr = [12, 30, 30, 60, 11, 12, 30];
let res = arr.reduce((acc, b, curInd) => {
let ind = arr.indexOf(b);
if (arr.filter(k => k == b).length > 1) {
if (acc.indexOf(ind) > -1) {
acc.push(curInd)
} else {
acc.push(ind);
}
}
return acc;
}, []);
console.log(res)
Below code will be easiest way to find indexes of duplicate elements
var dupIndex = [];
$.each(Arr1, function(index, value){
if(Arr1.filter(a => a == value).length > 1){ dupIndex.push(index); }
});
This should work for you

Take value from one array and add it on to the last value in another array

I have a problem with javascript arrays I am not sure how to approach.
First of all I want the second array's first value to be the same as the first value in the first array, and then add on to that.
I have an array and I want to add two values in the first array and push the result in to the second array, I then want to get the third value in the first array and add it to the last value in the second array, and then the fourth and fifth etc...
Example below because i'm finding it hard to explain!
var arr = [1, 2, 3, 4, 5];
var newArr = [];
End result of the second array (it's the result of adding consecutive values of the first array to the last value of the second array:
var newArr = [1, 3, 6, 10, 15];
I hope this makes sense - I'm finding it hard to think clearly about it!
This is a great candidate for reduce - you initialize you accumulator array with the first element of arr, and then you build your accumulator array as you iterate through the rest of the elements of arr:
var arr = [1, 2, 3, 4, 5];
var newArr = arr.reduce((acc, current) => {
acc.push((acc[acc.length - 1] || 0) + current);
return acc;
}, []);
console.log(newArr);
You can probably do it a smarter way using map/reduce or lodash, but the simplest option is a simple for loop:
var arr = [1, 2, 3, 4, 5];
var newArr = [];
for(let i = 0; i < arr.length; i++ ) { // iterate over input array
let incrementer = arr[i] // get value from input array
if( newArr[ newArr.length - 1 ] ) { // if the output array has a last value
incrementer += newArr[ newArr.length - 1 ] // add the last value
}
newArr.push(incrementer) // append the new value to end of output array
}
console.log(newArr)

Compounding values when mapping array?

I would like to compound values while mapping an array, I tried this but it didn't work:
var array = children.map((child, i) => {
return child.offsetHeight + array[i-1]
})
I would like an array that looks like this:
[1, 5, 3, 2]
to output:
[1, 6, 9, 11]
Using map is not a requirement. But I don't mind using something more intended than a for-loop.
Here an alternative way to other proposals and simple one-liner by using a forEach-loop:
let a = [1, 5, 3, 2],
b = [];
a.forEach((el, it) => { b.push(el + (b[it - 1] || 0)) });
console.log(b)
(b[it - 1] || 0) covers the first iteration where we would access b[-1]
You can use a combination of Array#map, Array#slice and Array#reduce :
.map( ... ) goes through your array
.slice( ... ) cuts a part from your array, from beginning to i+1
.reduce( ... ) returns the sum of the previously cut array
let children = [1, 5, 3, 2];
var array = children.map((child, i) =>
children.slice(0,i+1).reduce((acc, curr) => acc + curr, 0));
console.log(array);
This is one way:
const input = [1, 5, 3, 2];
const result = input.reduce((arr, x, i) =>
i == 0 ? [x] : [...arr, x + arr[arr.length - 1]]
, null)
console.log(result);
Reduce is better than map here, as you get access to the current state, rather than just the current item or the input array.
You can use array#reduce.
var result = [1, 5, 3, 2].reduce((r,v,i) => {
i ? r.push(r[i-1] + v) : r.push(v);
return r;
},[]);
console.log(result);
The easiest solution would be a combination of map slice and reduce:
arr = [1,5,3,2]
result = arr.map((elem, index) => arr.slice(0, index + 1).reduce((a,c) => a+c))
console.log(result)
You can do something like this, you must check at position 0 that array doesn't exist. This solution avoids using reduce and slice each step, improving performance;
var children = [1, 5, 3, 2]
var sum = 0;
var array = children.map((child, i, array) => {
sum = sum + child;
return sum;
})
console.log(array)
Example using for...of:
var arr = [1, 5, 3, 2]
var res = []
var c = 0
for (let item of arr) {
c += item
res.push(c)
}
console.log(res)
//[1, 6, 9, 11]
You could do this with reduce() method instead of map(). So if current index is not 0 you can take last element from accumulator and add current element.
const data = [1, 5, 3, 2]
const result = data.reduce((r, e, i) => {
r.push(i ? +r.slice(-1) + e : e)
return r;
}, []);
console.log(result)
You could also do this with just map() method using thisArg parameter and storing last value inside.
const data = [1, 5, 3, 2]
const result = data.map(function(e) {
return this.n += e
}, {n: 0});
console.log(result)
Or you could just create closure with IIFE and inside use map() method.
const data = [1, 5, 3, 2]
const result = (s => data.map(e => s += e))(0)
console.log(result)

Is there any method to find out which position my new number went to?

I have my array=[5,4,3,1] below, I want to .push(2), then .sort() my array and find out the new number's location in the array that I just pushed. I know the answer the new number's location is in array[1].
var array = [5,4,3,1];
array.push(2); //My new number
var sortedArray = arr.sort();
// sortedArray [1,2,3,4,5]
// The new number's position went to array[1]
Is there any method to find out which position my new number went to?
You could sort an array with indices and take the store index for serarching the inde fo the sorted array.
var array = [5, 4, 3, 1],
index = array.push(2) - 1,
indices = array
.map((_, i) => i)
.sort((a, b) => array[a] - array[b]);
console.log(index); // old index
console.log(indices.indexOf(index)); // new index
console.log(indices);
You can use findIndex.
const array = [5, 4, 3, 1];
const n = 32;
array.push(n);
const sortedArray = array.sort();
const index = sortedArray.findIndex(el => el === n);
console.log(sortedArray, index)
Note that you sort could be improved if you're using numbers and you want them to be in ascending order after the sort:
const sortedArray = array.sort((a, b) => b < a);
You can use reduce function.
This approach returns an array of indexes of number 2 if this is repeated.
In this case, will return an array with only one index.
Look at this code snippet
var array = [5,4,3,1];
array.push(2);
var indexes = array.sort().reduce((a, n, i) => {
if (n === 2) {
a.push(i);
}
return a;
}, []);
console.log(JSON.stringify(indexes));
See, returns an array with only one index.
Resource
Array.prototype.reduce()

Categories

Resources