Reputation: 1915
I generated this code for Longest Increasing Subsequence:
var lengthOfLIS = function(nums) {
if (nums.length === 0) return 0;
let result = 1;
const LISEndAt = new Array(nums.length).fill(1);
for (let i = 1; i < nums.length; i++) {
LISEndAt[i] = Math.max(1,
...LISEndAt.slice(0, i).map((item, j) => {
return nums[i] > nums[j] ? item + 1 : 0
}));
result = Math.max(LISEndAt[i], result);
}
return result;
}
let nums = [7,7,7,7,7,7,7];
console.log(lengthOfLIS(nums));
Can some one help me to understand this line:
LISEndAt[i] = Math.max(1,...LISEndAt.slice(0, i).map((item, j)
What is significance of three dots
and as we know map generates key value pairs, what is map
doing along with slice
?
Upvotes: 0
Views: 1786
Reputation: 7179
Before I can explain what the line you're asking about does, there are a few things to clear up.
...
...
is the spread syntax which expands the given iterable (array indices, object key-value pairs, etc). Here's an example where an existing array is used to create a new array with more elements:
const first = [1, 2, 3];
const second = [...first, 4, 5, 6];
console.log(second);
/* returns [1, 2, 3, 4, 5, 6] */
In your example, it is being used to provide multiple parameters to the Math.max()
function. Here's an example of that:
const candidates = [1, 5, 6, 2, 4];
const largest = Math.max(...candidates);
console.log(largest);
/* returns 6 */
Array#map
doesn't create key/value pairs. Instead, it creates a new array by performing an action on each element in the original array. Here's an example where a new array is created by doubling each item in the original array:
const original = [1, 2, 3];
const doubled = original.map(i => i * 2);
console.log(doubled);
/* returns [2, 4, 6] */
You can also access the index of each item in the original array:
const alphabet = ['A', 'B', 'C'];
const positions = alphabet.map((letter, index) => index);
console.log(positions);
/* returns [0, 1, 2] */
Array#slice
creates a new array that is a subset of the original array from the provided starting index until (but not including) the provided end index. Here's an example where a new array is created from the first three items of an existing array:
const superset = [1, 2, 3, 4, 5, 6];
const subset = superset.slice(0, 3);
console.log(subset);
/* returns [1, 2, 3] */
With all that in mind, let's take a look at the loop containing your line:
const nums = [10, 9, 2, 5, 3, 7, 101, 18];
const LISEndAt = new Array(nums.length).fill(1);
/* [1, 1, 1, 1, 1, 1, 1, 1] */
for (let i = 1; i < nums.length; i++) {
LISEndAt[i] = Math.max(1,
...LISEndAt.slice(0, i).map((item, j) => {
return nums[i] > nums[j] ? item + 1 : 0;
}));
}
LISEndAt
is being updated with each iteration of your for-loop. Each time, the next index is calculated as:
1
and any element in:LISEndAt
from 0 to the current iteration of the for-loop as modified by:map
which returns either:If we add some logging to your loop, you can see this happen in sequence:
const nums = [10, 9, 2, 5, 3, 7, 101, 18];
const LISEndAt = new Array(nums.length).fill(1);
console.log(`original: ${JSON.stringify(LISEndAt)}`);
for (let i = 1; i < nums.length; i++) {
const subset = LISEndAt.slice(0, i);
console.log(`sliced: [${subset.join(', ')}]`);
const someArray = subset.map((item, j) => {
console.log(`comparing ${nums[i]} > ${nums[j]} ? ${item + 1} : 0`);
return nums[i] > nums[j] ? item + 1 : 0;
});
console.log(`taking max of 1, ${JSON.stringify(...someArray)}`);
LISEndAt[i] = Math.max(1, ...someArray);
console.log(`iteration ${i}: ${JSON.stringify(LISEndAt)}`);
}
Upvotes: 1