Array spliting in JS not working as expected [duplicate] - javascript

This question already has answers here:
Array.prototype.fill() with object passes reference and not new instance
(7 answers)
Closed 1 year ago.
I have the following code, console.log is just to show what happens
function splitToChunks(array, parts) {
let result = new Array(parts).fill([]);
array.map((e,i)=> {console.log("r[",i%parts,"] gets -> ", e )|| result[i%parts].push(e)})
return result;
}
testing with arr = [0...11]
expected result would be:
[
[0, 4, 8],
[1, 5, 9],
[2, 6, 10],
[3, 7, 11],
]

The issue here is that the fill() array method passes by reference, not value, so it's actually the exact same "deep" object being passed to each sub-array, not new ones each time.
A quick workaround for this is to use fill() first and then map() the new array:
function splitToChunks(array, parts) {
let result = Array(parts).fill().map(e => []);
array.map((e,i) => { result[i % parts].push(e) });
return result;
}

Related

How to access the last element of an array using destructuring? [duplicate]

This question already has answers here:
Destructuring to get the last element of an array in es6
(17 answers)
Get first and last elements in array, ES6 way [duplicate]
(1 answer)
Closed 8 months ago.
Suppose I have an array like this: [2, 4, 6, 8, 10].
I want to access the first and last element of this array using destructuring, currently I'm doing this:
const array = [2, 4, 6, 8, 10];
const [first, , , , last] = array;
console.log(first, last);
But this is only works with arrays of length 5 and is not generic enough.
In Python I could do something like this:
array = [2, 4, 6, 8, 10]
first, *mid, last = array
print(first, last)
But in JS this is not possible since rest elements should be the last. So, is there some way to do this in JS or this is not possible?
You can use object destructuring and grab the 0 key (which is the first element) and rename it to first & then using computed property names you can grab the array.length - 1 key (which is the last element) and rename it to last.
const array = [2, 4, 6, 8, 10];
const { 0: first, [array.length - 1]: last } = array;
console.log(first, last);
You can also grab the length via destructuring and then use that to grab the last element.
const array = [2, 4, 6, 8, 10];
const { length, 0: first, [length - 1]: last } = array;
console.log(first, last);
Another simple approach to access the last element would be to use the Array.prototype.at method. This is not related to destructuring but it's worth knowing.
const array = [2, 4, 6, 8, 10];
console.log(array.at(-1));
Not necessarily using destructuring, but still concise in my opinion:
const arr = [1, 2, 3, 4, 5];
const [ first, last ] = [ arr.at(0), arr.at(-1) ];
console.log(first, last);
No, you can't use destructuring like that without convoluted workarounds.
A shorter, more readable alternative is to just pop:
const array = [2, 4, 6, 8, 10];
const [first, ...middle] = array;
const last = middle.pop();
console.log(first, middle, last);
Or, just access them by index:
const array = [2, 4, 6, 8, 10];
const first = array[0];
const last = array[array.length - 1];
console.log(first, last);

what's wrong with this sort function? javascript [duplicate]

This question already has answers here:
Why does Array.prototype.push return the new length instead of something more useful?
(6 answers)
Closed 1 year ago.
I want to find out the index of the element which is the lowest number in the array.
For ex: function getIndexToIns([3, 2, 10, 7], 4) will return 2 because if 4 is inserted into the array, the array should be [2, 3, 4, 7, 10] following ascending order. And 4 has the index of 2.
And my code snippet is as below and it shows error "TypeError: newArr.sort is not a function"
function getIndexToIns(arr, num) {
newArr = arr.push(num);
newArr.sort((a, b) => a-b);
return newArr.indexOf(num)
}
getIndexToIns([2, 10, 4], 50);
console.log(getIndexToIns([2, 10, 4], 50))
What is wrong in my code snippet???
.push() modifies the array in place, it does not return a new array. So newArray isn't an array.
You can create a new array with something like:
let newArr = [...arr, num];
Or perhaps:
let newArr = arr.concat([num]);
Welcome.
Remove newArr in newArr = arr.push(num); to become
arr.push(num);
Push method doesn't return the array itself but the new length. Ref
See documentation for Array.prototype.push():
The push() method adds one or more elements to the end of an array and
returns the new length of the array.
On top of that, push and sort methods mutate your original array. You should define your newArr like this:
const newArr = [...arr, num];
Then you can sort it and find out the index of element like you do it now.

Is there a more efficient way to remove all values from list a, which are present in list b? [duplicate]

This question already has answers here:
How to get the difference between two arrays in JavaScript?
(84 answers)
Closed 1 year ago.
This is what I have
function array_diff_very_fast(a, b) {
a = a.filter( el => !b.includes( el ) );
return a;
}
var temp = array_diff_very_fast([1,2,2,2,2,4,5,6], [1,2,6]);
console.log(temp);
and I want it to return [4,5].
I am working in code wars and the function works but it is not efficient enough.
You could take an approach with O(1) for searching the element in a data set, like a Set or an object.
Then omit using a variable just for storing a return value.
function array_diff_very_fast(a, b) {
const bb = new Set(b);
return a.filter(el => !bb.has(el));
}
console.log(array_diff_very_fast([1, 2, 2, 2, 2, 4, 5, 6], [1, 2, 6]));

Trying to create copies of an array using spread operator, but some how the array is being mutated

I'm trying to practice with the concept of immutability. I'm using the the spliceTest array as my main reference for creating copies of the array and mutating those. I'm coming to the problem when I declare removeOneItem variable, I somehow can't declare a new spread variable using the same reference of spliceTest.
const removeOneItem = [...spliceTest.splice(0,0), ...spliceTest.splice(1)];
const removeFive = [...spliceTest.splice(0,4), ...spliceTest.splice(5)];
const spreadTest = [...spliceTest];
console.log('removeOneItem:', removeOneItem)
console.log('spreadTest:', spreadTest, spliceTest)
console.log('removeFive:', removeFive)
Results::::::::::::
removeOneItem: [ 2, 3, 4, 5, 6, 7, 8, 9 ]
spreadTest: [] []
removeFive: [ 1 ]
According to MDN:
The splice() method changes the contents of an array by removing or
replacing existing elements and/or adding new elements in place.
This means, that the splice operation changes your array
Immutability of data is a cornerstone of functional programming and in general I'll do what you are trying to do: clone the data and mutate the clone. The following function takes an array and a series of sub-arrays. The sub-arrays consist of [startIndex, quantity]. It clones the original array by the spread operator and splices the clone according to the second parameter (...cutDeep). It will return an object with the original array and the cloned array. If you wrap everything in a function then your scope protects each return. Note on subsequent turns The second clone (secondResult.dissected) is spliced once more and the last log proves the original array is never mutated.
Demo
const data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 'd', 'e', 'f'];
const dissect = (array, ...cutDeep) => {
let clone = [...array];
for (let [cut, deep] of cutDeep) {
clone.splice(cut, deep);
}
return {
original: array,
dissected: clone
};
}
const firstResult = dissect(data, [2, 3], [5, 2], [9, 1]);
const secondResult = dissect(data, [3, 2], [10, 1]);
console.log(JSON.stringify(firstResult));
console.log(JSON.stringify(secondResult));
console.log(JSON.stringify(dissect(secondResult.dissected, [0, 2], [5, 1])));
console.log(JSON.stringify(data));
The problem is that you use splice when you most likely want to use slice.
splice is used for mutating an array, while slice is used to select a sub-array.
const sliceTest = [1, 2, 3, 4, 5, 6, 7, 8, 9];
// select a sub-array starting from index 1 (dropping 0)
const removeOneItem = sliceTest.slice(1);
// select a sub-array starting from index 5 (dropping 0, 1, 2, 3, and 4)
const removeFive = sliceTest.slice(5);
// spread the full array into a new one
const spreadTest = [...sliceTest];
// array log helpers (leave these out in your code)
const toString = array => "[" + array.join(",") + "]";
const log = (name, ...arrays) => console.log(name, ...arrays.map(toString));
log('removeOneItem:', removeOneItem)
log('spreadTest:', spreadTest, sliceTest)
log('removeFive:', removeFive)
slice already creates a shallow copy of the array, so [...arr.slice(i)] is not needed.

Most efficient way to flatten Array<Array<T> | T> in JavaScript [duplicate]

This question already has answers here:
Merge/flatten an array of arrays
(84 answers)
Closed 3 years ago.
I want to create a function that accepts an array of both arrays and literals (or maybe objects) and flattens it to a single dimensional array. For example a valid input would be [5, [2, 3], 7, [9, 0, 1]], and the output of that input should be [5, 2, 3, 7, 9, 0, 1].
This is the code I have so far. There is nothing wrong with it, I just want to make sure it's as efficient as possible (it also needs to be es5 compatible).
function flattenArray(list) {
var result = [];
for (var index = 0; index < list.length; index++) {
result.push(list[index] instanceof Array ? list[index] : [list[index]]);
}
return [].concat.apply([], result);
}
console.log(flattenArray([5, [2, 3], 7, [9, 0, 1]]));
How about simply using Array.flat
function flattenArray(list) {
return list.flat()
}
console.log(flattenArray([5, [2, 3], 7, [9, 0, 1]]));
This seems to be second fastest ( based on the test link attached below ) and ES5 compatible
console.log([].concat.apply([],[5, [2, 3], 7, [9, 0, 1]]))
Performace test
Cocerning your code: There is no sense in wrapping single elements into arrays, .concat will handle them correctly, in other words:
[1].concat([2], 2)
just works, there is no need for wrapping 2 into [2]. That turns your code into a oneliner.

Categories

Resources