Lodash difference between _.remove() and _.pullAt() - javascript

What is the difference between lodash _.remove() and _.pullAt() functions?
var arr1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
_.remove(arr1, function (item) {
return item == 1
});
var arr2 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
_.pullAt(arr2, 1);
console.log(arr1.toString() + '\n' + arr2.toString());
// both result to [0,2,3,4,5,6,7,8,9,]
I've crated fiddle and read the description on the lodash site that states that _.remove()
Removes all elements from array that predicate returns truthy for and returns an array of the removed elements
and _.pullAt()
Removes elements from array corresponding to the given indexes and returns an array of the removed elements
Is there any difference at all? Or am I missing something?

Even your example made different things:
remove splices element by value, while pullAt by index.
Let's check it with different array [0, 3, 1, 1, 5]:
remove: [0, 3, 5] - all 1 items removed
pullAt: [0, 1, 1, 5] - arr[1] was spliced
You also can write other filters than compare by value with remove:
_.remove(arr, item => item % 2); // removes all odd numbers
_.remove(arr, user => user.deleted); // splice deleted users
_.remove(arr, item => item < 5); // and etc.

Related

how to solve targetArrayInGivenOrder in JavaScript

Write a function that takes two arrays of integers (nums and index) and
returns a target array under the following rules:
Initially target array is empty.
From left to right read nums[i] and index[i], insert at index index[i] the
value nums[i] in target array.
Repeat the previous step until there are no elements to read in nums and index.
Example 1
Input: nums = [0, 1, 2, 3, 4], index = [0, 4, 1, 2, 3]
Output: [0, 4, 1, 2, 3]
Example 2
Input: nums = [1, 2, 3, 4, 0], index = [0, 1, 2, 3, 0]
Output: [1, 2, 3, 4, 1]
Your example does not match your description. According to your example, you want to insert the nums[index[i]] in your target array's i'th position.
You can do this using Javascript's array.map function like this -
const targetArray = index.map(i => nums[i]);
You may need to add necessary sanity checks as well depending on the contexts.
You can simply achieve this by using Array.forEach() along with Array.splice() method.
Live Demo :
const numsArr = [1, 2, 3, 4, 0];
const indexArr = [0, 1, 2, 3, 0];
let outputArr = [];
numsArr.forEach((elem, index) => {
outputArr.splice(index, 0, numsArr[indexArr[index]]);
});
console.log(outputArr);

How to split nested array into "rows" with limited size

I have an array of arrays of different sizes. The goal is to generate "rows" where each row can contain a max of 12 elements.
For example:
Input data can be something like this:
const groups = [[1,2,3,4],[1,2,3,4,5,6], [1,2,3,4,5,6,7,8,9,10,11,12], [1,2,3,4,5,6,7], [1,2,3],[1,2,3]]
groups[0].length + groups[1].length = 10 -> row0
groups[2].length = 12 -> row1
groups[3].length + groups[4].length = 10 -> row3
groups[5].length = 3 -> row4
Output for such array should be:
[[[1,2,3,4], [1,2,3,4,5,6]], [[1,2,3,4,5,6,7,8,9,10,11,12]], [[1,2,3,4,5,6,7], [1,2,3]], [[1,2,3]]]
I was thinking of a recursive function for this but couldn't figure out how to solve it.
You can use Array#reduce() to do this.
The code first checks if the current last element (last "row") has more than 12 numbers in it if you add the next group:
(acc[acc.length - 1].flat().length + cv.length) <= 12
if it will be less than 12, the elements will get pushed into the "row":
acc[acc.length - 1].push(cv)
and if not, a new "row" will be added to the outer array:
acc.push([cv])
const groups = [[1, 2, 3, 4],[1, 2, 3, 4, 5, 6],[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],[1, 2, 3, 4, 5, 6, 7],[1, 2, 3],[1, 2, 3]];
const rows = groups.reduce((acc, cv) => {
(acc[acc.length - 1].flat().length + cv.length) <= 12 ?
acc[acc.length - 1].push(cv) :
acc.push([cv])
return acc
}, [[]]);
console.log(JSON.stringify(rows))
Here's one way to solve it recursively:
const regroup = (max, [g, ...gs], filled = [], curr = [], cc = 0) =>
g == undefined
? filled .concat ([curr])
: g .length + cc <= max
? regroup (max, gs, filled, curr .concat ([g]), cc + g.length)
: regroup (max, gs, filled .concat ([curr]), [g], g .length)
const groups = [[1, 2, 3, 4], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
[1, 2, 3, 4, 5, 6, 7], [1, 2, 3], [1, 2, 3]]
console .log (regroup (12, groups))
.as-console-wrapper {max-height: 100% !important; top: 0}
We pass the maximum size and the list of items, and then we default three parameters:
filled will track the output rows we've filled; it starts with an empty array
curr stores the row we're working on; it also starts with an empty array
cc stores the count of all elements in the current row; it starts with zero
On each recursive call, we have one of three possibilities:
There are no more arrays to process, and we return all the filled rows with the current row appended.
The next array is small enough to fit in the current row, and we update the current to include it, and the current count to accommodate it.
The next array is too large, and we add the existing current row to the filled ones, and start a new current row with this array, setting the count appropriately.

method to check if a specific number with a group of numbers exists within an array in javascript

var numbers = [1, 2, 3, 4, 5, 6, 7, 8];
need to check if 2, 3, 4 exist in the array. Only has to be 1 of these numbers to return true...not all. What's the best approach. I was thinking lodash includes, but I believe I can only pass in a single value.
Using Array#some and Array#includes:
const hasAny = (arr = [], nums = []) =>
nums.some(n => arr.includes(n));
console.log( hasAny([1, 2, 3, 4, 5, 6, 7, 8], [2, 3, 4]) );
If you want to get the intersection, you can filter the first array by the second array, or rather, whether or not the second array contains each element of the first. You can see which members were included, or check the size of the new array > 0 if you need a boolean (or use Mr Badawi's .some method).
var numbers = [1, 2, 3, 4, 5, 6, 7, 8];
var needs = [2, 3, 4 ];
var check = numbers.filter(x=>needs.includes(x));
console.log(check);
var numbers = [3, 5, 6, 7, 8, 12, 20];
var needs = [2, 3, 4 ];
var check = numbers.filter(x=>needs.includes(x));
console.log(check);

What to do if i want to show the first 5 elements from the array by using forEach loop?

There are 10 elements in an array. What to do if i want to show the first 5 elements from the array by using forEach loop?
let arrays =[1, 2, 4, 6, 7, 44, 5, 7, 6]
arrays.forEach(array =>{}) //
To show the first 5 elements from the array by using forEach loop, you can use if statement
const arrays = [1, 2, 4, 6, 7, 44, 5, 7, 6];
arrays.forEach(function(value, index, array) {
if(index <= 4) {
document.write(value + "<br>");
}
});
Where parameters:
Index = The index of the current element.
Value = The value of the current element.
Array = The array of the current element.
https://www.w3schools.com/jsref/jsref_foreach.asp
https://www.w3schools.com/js/js_if_else.asp

javascript, forEach and removeChild unpredictable behavior

I wish to remove all items from a list and replace them with others
var list = document.querySelector("ul");
[].forEach.call(list.childNodes, list.removeChild.bind(list));
The code above does not work as expected, instead it removes only half the items (leaving every second item in the list).
If i change it to
var list = document.querySelector("ul");
[].slice.call(list.childNodes).forEach(list.removeChild.bind(list));
Then it works as expected,
can anyone explain ?
In the first one you are mutating an array you are iterating over.
In the second you are making a copy and then iterating over it.
The following is another option that doesn't require making a copy:
for(; list.firstChild; list.removeChild(list.firstChild));
This removes the firstChild while it is not null.
Concept
To explain the "unpredictable" behavior in the first scenario, consider this case:
var array = [0, 1, 2, 3, 4, 5, 6, 7];
This makes the behavior easier to explain without the distracting .call() and .bind() methods to wrap your head around.
array.forEach(function(num, index) {
console.log(num, index);
array.splice(index, 1);
});
You may be wondering why the output is:
0 0
2 1
4 2
6 3
But it's actually really simple. .forEach() iterates over the indices until i < array.length is no longer satisfied, while at the beginning of each iteration, your array looks like this:
[0, 1, 2, 3, 4, 5, 6, 7];
^
0
[1, 2, 3, 4, 5, 6, 7];
^
1
[1, 3, 4, 5, 6, 7];
^
2
[1, 3, 5, 6, 7];
^
3
[1, 3, 5, 7];
^
(4 < array.length) !== true
This is what happens when you manipulate an array being iterated over within a call to .forEach().
For the case where you execute [].slice.call(array), all you're doing is making a shallow copy of all the indices of the array. This allows you to iterate over the copy's indices while removing the nodes from the original.
Below is a comprehensive example, but make sure your browser supports ES6 template strings.
Demo
var array = [0, 1, 2, 3, 4, 5, 6, 7];
document.write(`<p>original.forEach()</p>`);
array.forEach(function(num, index) {
document.write(`<pre>num: ${num}, index: ${index}, array: [${array}]</pre>`);
array.splice(index, 1);
});
document.write(`<pre>result: [${array}]</pre>`);
array = [0, 1, 2, 3, 4, 5, 6, 7];
var copy = array.slice();
document.write(`<p>copy.forEach()</p>`);
copy.forEach(function(num, index) {
document.write(`<pre>num: ${num}, index: ${index}, array: [${array}]</pre>`);
array.splice(array.indexOf(num), 1); // removing by reference, not by index
});
document.write(`<pre>result: [${array}]</pre>`);
body > * {
padding: 0;
margin: 0;
}

Categories

Resources