Lodash: Array without last element, no mutation - javascript

I'm looking for a way to retrieve my array without the last element, and without being mutated.
_.remove does mutate the array and searches by value not index (even if it was asked there)
_.without searches by value, not index
I have _.filter(array, function(el, i) { return i != array.length -1}); but siouf, not really explicit and it needs array to be stored somewhere.
Thanks

I was looking for something like "butlast", but I found initial, which does the job:
var xs = [1, 2, 3, 4];
var xs2 = _.initial(xs);
console.log(xs, xs2); // [1, 2, 3, 4] [1, 2, 3]

Array.prototype.slice might help you.
var array = [1,2,3,4,5];
var newArr = array.slice(0, -1);
console.log(array); // [1, 2, 3, 4, 5]
console.log(newArr); // [1, 2, 3, 4]
Of course you are also able to do it with lodash
Thanks

Try this:
_.take(arr, arr.length-1)

Related

How would one add items to the beginning of an array with Lodash?

I've been searching for a while to add items to the beginning of an array with lodash. Unfortunately I can't seem to find anything other than lodash concat (to the end of the array). The docs don't seem to say anything about it either.
I got the following code:
const [collection, setCollection] = useState({
foo: [1, 2, 3]
});
const addToCollection = (key, items) => {
setCollection(prevCollection => ({
...prevCollection,
[key]: _.concat(prevCollection[key] || [], items)
}));
};
But this concats all the items to the end. I don't want to sort them every time because that uses unnessecary processing power, I would much rather just add them to the beginning because the API always pushes the items already sorted
How would I accomplish this:
addToCollection('foo', [4, 5, 6]);
console.log(collection['foo']) // [4, 5, 6, 1, 2, 3];
Instead of what is happening now:
addToCollection('foo', [4, 5, 6]);
console.log(collection['foo']) // [1, 2, 3, 4, 5, 6];
Try swapping the arguments:
_.concat(items, prevCollection[key] || [])
Or vanilla JS is pretty easy too:
Collection.unshift('addMe', var, 'otherString' )
https://www.w3schools.com/jsref/jsref_unshift.asp#:~:text=The%20unshift()%20method%20adds,use%20the%20push()%20method.
I know you asked for lodash but I figured this is a good thing to be aware of too :)
EDIT:
To clarify, this works the same whether you're pushing defined vars, string, arrays, objects or whatever:
let yourArray = [1,2,3];
let pushArray = [1,2,3,4];
let anotherArray = [7,8,9];
yourArray.unshift(pushArray, anotherArray);
will push "pushArray" and "anotherArray" to the begining of "yourArray" so it's values will look like this:
[[1,2,3,4], [7,8,9], 1,2,3]
Happy Coding!

Return spreaded array in arrow function

Let's assume i have this type of array:
[ [1, 2], [3, 4] ]
What i need to do is to get nested elements on the higher layer, to make it look like:
[1, 2, 3, 4]
I am trying to reach that in functional way, so the code look's like this:
const arr = [ [1, 2], [3, 4] ]
const f = Array.from(arr, x => ...x)
But that comes up with Unexpected token ... error. So what's the way to do it right?
You can use the flat method of Array:
const inp = [ [1, 2], [3, 4] ];
console.log(inp.flat());
In your case, the spread syntax is not an operator that you can use in that way, that's why the error.
As #MarkMeyer correctly pointed out in the comments, the flat is not supported yet by Edge and Internet Explorer. In this case you could go for a solution with reduce:
const inp = [[1,2], [3,4]];
console.log(inp.reduce((acc, val) => acc.concat(...val), []));
Array.from will produce an item for every item in the array passed in. It looks at the length of the passed in iterable and iterates over the indexes starting at 0. So no matter what you do in the callback (assuming it's valid), you're going to get an array of length 2 output if you pass in a two-element array.
reduce() is probably a better option here:
let arr = [ [1, 2], [3, 4] ]
let flat = arr.reduce((arr, item) => [...arr, ...item])
console.log(flat)
You could create an iterator for the array and spread the array by using another generator for nested arrays.
function* flat() {
for (var item of this.slice()) {
if (Array.isArray(item)) {
item[Symbol.iterator] = flat;
yield* item
} else {
yield item;
}
}
}
var array = [[1, 2], [3, 4, [5, 6]]];
array[Symbol.iterator] = flat;
console.log([...array]);

JS - For Loops Pushing Array

I have an initial array,
I've been trying to change values (orders) by using pop, splice methods inside a for loop and finally I push this array to the container array.
However every time initial array is values are pushed. When I wrote console.log(initial) before push method, I can see initial array has been changed but it is not pushed to the container.
I also tried to slow down the process by using settimeout for push method but this didnt work. It is not slowing down. I guess this code is invoked immediately
I would like to learn what is going on here ? Why I have this kind of problem and what is the solution to get rid of that.
function trial(){
let schedulePattern = [];
let initial = [1,3,4,2];
for(let i = 0; i < 3; i++){
let temp = initial.pop();
initial.splice(1,0,temp);
console.log(initial);
schedulePattern.push(initial);
}
return schedulePattern;
}
**Console.log**
(4) [1, 2, 3, 4]
(4) [1, 4, 2, 3]
(4) [1, 3, 4, 2]
(3) [Array(4), Array(4), Array(4)]
0 : (4) [1, 3, 4, 2]
1 : (4) [1, 3, 4, 2]
2 : (4) [1, 3, 4, 2]
length : 3
When you push initial into schedulePattern, it's going to be a bunch of references to the same Array object. You can push a copy of the array instead if you want to preserve its current contents:
schedulePattern.push(initial.slice(0));
Good answer on reference types versus value types here: https://stackoverflow.com/a/13266769/119549
When you push the array to schedulepattern, you are passing a reference to it.
you have to "clone" the array.
use the slice function.
function trial(){
let schedulePattern = [];
let initial = [1,3,4,2];
for(let i = 0; i < 3; i++){
let temp = initial.pop();
initial.splice(1,0,temp);
console.log(initial);
schedulePattern.push(initial.slice());
}
return schedulePattern;
}
​
You have to know that arrays are mutable objects. What does it mean? It means what is happening to you, you are copying the reference of the object and modifying it.
const array = [1,2,3]
const copy = array;
copy.push(4);
console.log(array); // [1, 2, 3, 4]
console.log(copy); // [1, 2, 3, 4]
There are a lot of methods in Javascript which provide you the way you are looking for. In other words, create a new array copy to work properly without modify the root.
const array = [1,2,3]
const copy = Array.from(array);
copy.push(4);
console.log(array); // [1, 2, 3]
console.log(copy); // [1, 2, 3, 4]
I encourage you to take a look at Array methods to increase your knowledge to take the best decision about using the different options you have.

How reduce() higher order function works?

Below is reduce() function
function reduce(array, combine, start) {
let current = start;
for (let element of array) {
current = combine(current, element);
}
return current;
}
Now this is the question which i am solving
Use the reduce method in combination with the concat method to “flatten” an array of arrays into a single array that has all the elements of the original arrays.
Here is the solution
let arrays = [[1, 2, 3], [4,5], [6]];
console.log(arrays.reduce((flat,current)=> flat.concat(current), []));
// → [1, 2, 3, 4, 5, 6]
Now if i try this
let arrays = [[1, 2, 3], [4, [79],5], [6]];
console.log(arrays.reduce((flat, current) => flat.concat(current), []));
I get this
[1, 2, 3, 4, [79], 5, 6]
It means that this solution can get a flatten array only up to two nested array
But how it works for this
arrays = [[1, 2, 3], [4,5], [6]];
Because in reduce() function i am using
for( let elements of array) which by the way if i use
It works like this
array = [1,4,6,[6,7],7,6,8,6];
for(element of array)
console.log(element);
// 146[6,7]7686
It does not gets the value from nested array
Then how does it for the first solution
And how to write solution which works for any number of nested array i know it will use recursion but how ?
why this function can only flatten array up to one level deep ?
let arrays = [[1, 2, 3], [4, [79],5], [6]];console.log(arrays.reduce((flat, current) => flat.concat(current), []))
Because the reduce function doesn't know if you are trying to concatenate a primitive (a number) or an array. When the reduce functions tries to concatenate two arrays, it produces a single array, but it doesn't know if every element in the array is a number or an array.
Then, as you suggested, you can use recursion:
function flatten(arrayToFlatten){
return arrayToFlatten.reduce((prev, next)=>{
if(!Array.isArray(next)){ // Base case, when you have a number
return prev.concat(next);
} else { // Recursive case, when you have an array
return prev.concat(flatten(next));
}
}, []);
}
You can do:
const arrays = [[1, 2, 3],[4, [79], 5],[6]];
const getFlatten = array => array.reduce((a, c) => a.concat(Array.isArray(c) ? getFlatten(c) : c), []);
const result = getFlatten(arrays);
console.log(result);

Return an array with all the elements of the passed in array but the last

Instructions:
Write a function called getAllElementsButLast.
Given an array, getAllElementsButLast returns an array with all the elements but the last.
Below is my code that will not pass the requirements for the question. I am not sure why this is not correct even though I am getting back all the elements besides the last.
var arr = [1, 2, 3, 4]
function getAllElementsButLast(array) {
return arr.splice(0, arr.length - 1)
}
getAllElementsButLast(arr) // [1, 2, 3]
I think the reason why it's not accepted is because with splice() you change the input array. And that's not what you want. Instead use slice(). This method doesn't change the input array.
var arr = [1, 2, 3, 4]
function getAllElementsButLast(array) {
var newArr = array.slice(0, array.length - 1);
return newArr;
}
var r = getAllElementsButLast(arr);
console.log(r);
console.log(arr);

Categories

Resources