While and array - Using a loop with array - javascript

Can someome explain to me how New Array, and Array works with this loop? Also, anyone knows if is possible of doing a array and inside this array a function? Because this way of doing seem kinda wrong considering POO and SRP
Here`s the link of the exercise: https://www.codewars.com/kata/569e09850a8e371ab200000b/train/javascript
function preFizz(n) {
let output = new Array();
let num = 1;
while(output.length < n){
output.push(num);
num += 1;
}
return output;
}

Ok, i found the answer thanks to epascarello and Abdennour TOUMI. Here´s the link where of the answer: How to create an array containing 1...N
Basically i was trying to finding more about arrays and loops(In a more pratice way), this codes maked more easier to understand
let demo = (N,f) => {
console.log(
Array.from(Array(N), (_, i) => f(i)),
)
}

Why not use a traditional for-loop? It has declaration, conditional, and increment functionality built right in.
const preFizz = (n) => {
const output = [];
for (let num = 1; num <= n; num++) {
output.push(num);
}
return output;
}
console.log(...preFizz(10));
A more modern version of this would be to declare an array of a specified length and map the indices.
const preFizz = (n) => Array.from({ length: n }).map((_, i) => i + 1);
console.log(...preFizz(10));

Related

LeetCode: (26: Remove Duplicates from Sorted Array)

I'm trying to solve a problem in LeetCode, which is (26. Remove Duplicates from Sorted Array), and it's saying that my code is incorrect, while it works perfectly in VS Code.
Here is the code:
let nums = [1, 1, 2]
let k = 0
const removeDuplicates = nums => {
nums = [...new Set(nums)]
k = nums.length
return k + '\n' + nums
}
console.log(removeDuplicates(nums))
my question is why does the code works in vs code but not in Leet code?
This is the code in Leet Code This is the code in VS Code
var removeDuplicates = function(nums) {
const set = new Set(nums);
let i = 0;
set.forEach(num => {
nums[i] = num
i++
})
return set.size;
};
The question asks for a numeric result, but your removeDuplicates function returns a multi-line string.
The duplicates should be removed in-place, that is, without using auxiliary data structures like new Set(…).

Generate array from 0 to N with custom increment in Javascript

Problem Description
I am trying to generate an array using keys() and .map() methods, given a preexisting array with length = arrLength, such that only items at a position that are multiples of step are generated. Here is an example,
const arrLength = 20;
const step = 5;
const newArr = [...Array(arrLength).keys() ].map((i) => i + step);
console.log(newArr) ;
// expected: 0,5,10,15,20
// recieved : 5,6,7,...,24
I am particlarly confused as to how to increment the left hand side variable i in map((i) => ... ).
Restrictions
I want to implement this in one line using the keys method and Array and possibly map, so no for loop.
Things I have tried
I tried the following signatures instead
Array(arrLength).fill().map((_, i) => i+step) ,
Array.from(Array(arrLength), (_, i) => i+step),
Array.from({ length: arrLength }, (_, i) => i+step)
but with no success. I have further tried to find a way to increment the i variable using functional syntax but with no success as wel.
const arrLength = 20;
const step = 5;
const arr = [];
for (let i = 0; i<= arrLength; i+=step){
arr.push(i);
}
console.log(arr);
Or
const arrLength = 20;
const step = 5;
const newArr = [...Array(Math.floor(arrLength/step) + 1).keys() ].map((i) => i * step);
console.log(newArr);
range function work with ES4
Using Array.from can pass an object has property length in it
const range = (start, stop, step) => Array.from({ length: (stop - start) / step + 1}, (_, i) => start + (i * step));
console.log(range(0, 20, 5))
Stumbled upon this, and while looking at the answers I came up with this. This just basically creates an array with incrementing numbers, but could be extended easily.
This reduce function generates desired array by taking the index i of given element and then we combine what we already got in the previous recursive step (the a variable) with the incremental value i.
const arr = new Array(52).fill(0).reduce((a,_,i) => [...a, i],[])

Custom class that returns an array given start and end parameters in javascript

I want to create a "custom array" that takes in a start and end index and generates an array from that. My knowledge of classes in javascript is fairly limited, but I know Java fairly well. I couldn't figure out how to extend a class (I kept getting an error) so what I came up with is the following:
class RangedArray{
constructor(startNum, endNum){
this.startNum = startNum;
this.endNum = endNum;
this.timeslot = this.createTimeslot();
}
createTimeslot(){
let index = 0;
let arr = [];
for (let num = this.startNum; num <= this.endNum; num++) {
arr[index] = num;
index++;
}
return arr;
}
}
This code does what I want, however if I want to access my array I would have to do something like this
let obj = new RangedArray(4, 21);
let timeslot1 = obj.timeslot;
What would be ideal is to do this in a single line. By that I mean I want to be able to use it like
let obj = new RangedArray(4, 21);
obj[0] = 1;
Like I said I think this can be done by extending the Array class but I'm not sure how to do that. I would basically want to override the regular array constructor inside the RangedArray class. So what would I have to do to get this functionality?
There's no need for a class here, it'll just make things unnecessarily complicated. Make a standard function instead, one that constructs and returns a plain array that you need:
const makeRangedArray = (startNum, endNum) => {
const arr = [];
for (let num = startNum, index = 0; num <= endNum; num++, index++) {
arr[index] = num;
}
return arr;
}
const arr = makeRangedArray(4, 21);
arr[0] = 999;
console.log(arr);
I agree with the previous comment. You don't need to use classes for this, I think a pretty elegant way would be to put it like this:
const makeRangedArray = (start, end, length = end - start + 1) =>
Array.from({ length }, (_, i) => start + i)
const arr = makeRangedArray(4, 21);
arr[0] = 999;
console.log(arr);

Nested for loops are not generating random values for each iteration [duplicate]

I was toying a bit and was trying to instantiate a new array of length x, where all elements of that array were initialized to a value y:
var arr = new Array(x).fill(y);
This works well if the value of y is anything other than an object.
Meaning that if y is an object, the following is true:
var arr = new Array(2).fill({});
arr[0] === arr[1]; //is true;
arr[0].test = 'string';
arr[1].test === 'string'; //is also true;
Is there any way to state that a new object should be created for each element while using the fill-function? Or should I just convert it to a loop?
You can first fill the array with any value (e.g. undefined), and then you will be able to use map:
var arr = new Array(2).fill().map(u => ({}));
var arr = new Array(2).fill().map(Object);
The accepted answer is good and would work in 90% of cases.
But if you are making high-performance JS application, and if you work with big/huge arrays, Array.map(..) creates big overload in both - memory and processor use, as it creates a copy of an array.
I recommend to use the classic for loop:
a = new Array(ARRAY_SIZE);
for (var i = 0; i < ARRAY_SIZE; i++) {
a[i] = [];
}
// or it's one line alternative
for (var i = 0, a = []; i < ARRAY_SIZE; a[i++] = []);
I tested six alternatives and got this:
Array.map(), as proposed above (11x times!!! slower):
a = new Array(ARRAY_SIZE).fill().map(u => { return []; });
for loop, the best one (fastest):
// Standard multi-line way
a = new Array(ARRAY_SIZE);
for (var i = 0; i < ARRAY_SIZE; i++) {
a[i] = [];
}
// One line syntax
for (var i = 0, a = []; i < ARRAY_SIZE; a[i++] = []);
forEach (6x time slower):
a = new Array(ARRAY_SIZE).fill();
a.forEach((val, i) => {
a[i] = [];
})
[UPDATE 2020-08-27] One more way proposed by Ilias Karim below
Array.from (30x times!!! slower) - apparently worse in terms of performance, despite the nicest syntax :(
a = Array.from({ length: ARRAY_SIZE }, () => []);
[..Array(..)] (5x times!!! slower)
a = [...Array(ARRAY_SIZE)].map(_=>([]))
Array.push(..), second place in terms of performance (2x times!!! slower)
let a = [], total = ARRAY_SIZE;
while(total--) a.push([]);
PS. I used this fiddle for tests.
One performant solution:
Array.from({ length: 5 }, () => new Object())
Shortest Possable:
let node = [...Array(2)].map(_=>({}))
console.log(node)
Ilias Karim's answer is most excellent. I just did the following:
a = Array.from({length:l}, () => new Array(c).fill(prefix));
to create a pre-filled 2D array of the specified size, l by c, filled with prefix. Now my code can fill in the slots in the 2D matrix that need non-prefix values.
I wrote a blog post about this: http://www.samhenderson.xyz/posts/12
But the TLDR is that if you want to avoid chaining multiple function e.g. fill, map. And want to avoid writing a loop, then you can use:
const array = Array.from({ length: 2 },()=>({}))
For an array of arrays:
const array = Array.from({ length: 2 },()=>([]))
To add to answers that explain the aliasing issue and how to solve it, here's a handy function that can be used to create arrays with cleaner syntax for the caller:
const array = (length, fill) =>
[...Array(length)].map((_, i) =>
typeof fill === "function" ? fill(i) : fill
);
// usage:
const a = array(3, i => array(3, j => [i, j]));
a[0][0][0] = -42;
console.log(a);
Note that you still need to use a callback function for non-primitive values. This is actually a feature as it exposes the index and lets you provide arbitrary logic to fill the element. If you're concerned about accidentally passing a non-primitive, non-function object as the fill value, you can throw an error.
If you really want to be able to pass an object directly and have it copied under the hood, here's an adjustment that pretty much prohibits aliasing:
const array = (length, fill) =>
[...Array(length)].map((x, i) =>
typeof fill === "function" ? fill(i) :
typeof fill === "object" ? _.cloneDeep(fill) : fill
);
// usage:
const a = array(2, array(2, {foo: 3}));
a[0][0].foo = 42;
console.log(a);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
In general, I suggest avoiding .fill() almost entirely in favor of the spread syntax [...Array()] because it's easy to forget about the aliasing behavior and wind up with a frustrating bug.
If speed matters, use a traditional for loop:
const array = (length, fill) => {
const a = [];
for (let i = 0; i < length; i++) {
a[i] = typeof fill === "function" ? fill(i) : fill;
}
return a;
};
// usage:
const a = array(2, () => array(2, Object));
a[0][0].foo = 42;
console.log(a);

My function does not return the expected output and I can't figure out why; can somebody point out something I'm missing? [duplicate]

This question already has answers here:
Array.fill(Array) creates copies by references not by value [duplicate]
(3 answers)
Closed 3 years ago.
my function has to take 2 arrays and if one of the arrays is shorter than the other it needs to fill in the blanks with nulls.
so i could do this easier now that i think about it but i would really like to know what i have missed.
the specific part of my code is the nested forEach loops i cant understand that when i invoke my function like this
fillSquare([1,2,3],[1,2,3,4,5])
I get [[1,2,3,4,5],[1,2,3,4,5]] instead of [[1,2,3,null,null][1,2,3,4,5]]
const fillSquare = arr => {
const maxArrayLength = Math.max(
...arr.map(arr => {
return arr.length;
})
);
let arrayMatrix = new Array(arr.length).fill(
new Array(maxArrayLength).fill(null)
);
arr.forEach((arry, mainIndex) => {
arry.forEach((item, subIndex) => {
console.log(mainIndex, "<--main", "sub-->", subIndex, "=", item);
arrayMatrix[mainIndex][subIndex] = item;
});
});
console.log(arrayMatrix);
return arrayMatrix;
};
When debugging, it seems:
let arrayMatrix = new Array(arr.length).fill(
new Array(maxArrayLength).fill(null)
);
// arrayMatrix[1] == arrayMatrix[0] => true
is only creating 1 array instance. setting 1 value on one sets it on both.
heres how to fix your issue
let arrayMatrix = new Array(arr.length).fill(0).map( _ => new Array(maxArrayLength).fill(null));
this is my version - now immutable
function fillSquare(arr) {
let clone = [...arr]
let maxDepth = arr.reduce( (c, subarr) => c = Math.max(c, subarr.length), 0)
clone.forEach((subarr, index) => {
let len = clone[index].length;
clone[index].length = maxDepth;
clone[index].fill(null, len, maxDepth);
})
return clone;
}
the import notes are you can set the length and fill the gaps. Also check out reduce if you need.
const fillSquare = function(arr){
let minLengthArr = arr[0];
let maxLength = arr[1].length;
if(arr[1].length < arr[0].length){
minLengthArr= arr[1];
maxLength = arr[0].length;
}
let itemsToPush = maxLength - minLengthArr.length;
for(let i=0;i<itemsToPush;i++){
minLengthArr.push(null);
}
return arr;
}
var r = fillSquare([[1,2,3],[1,2,3,4,5]]);
console.log(r);

Categories