Lodash remove from string array - javascript

I have an array of string and want to instantly remove some of them. But it doesn't work
var list = ['a', 'b', 'c', 'd']
_.remove(list, 'b');
console.log(list); // 'b' still there
I guess it happened because _.remove function accept string as second argument and considers that is property name. How to make lodash do an equality check in this case?

One more option for you is to use _.pull, which unlike _.without, does not create a copy of the array, but only modifies it instead:
_.pull(list, 'b'); // ['a', 'c', 'd']
Reference: https://lodash.com/docs#pull

As Giuseppe Pes points out, _.remove is expecting a function. A more direct way to do what you want is to use _.without instead, which does take elements to remove directly.
_.without(['a','b','c','d'], 'b'); //['a','c','d']

Function _.remove doesn't accept a string as second argument but a predicate function which is called for each value in the array. If the function returns true the value is removed from the array.
Lodas doc: https://lodash.com/docs#remove
Removes all elements from array that predicate returns truthy for and
returns an array of the removed elements. The predicate is bound to
thisArg and invoked with three arguments: (value, index, array).
So, if you want to remove b from your array you should something like this:
var list = ['a', 'b', 'c', 'd']
_.remove(list, function(v) { return v === 'b'; });
["a", "c", "d"]

Related

In javascript, array is showing 'pass by value' behavior instead of 'pass by reference'

I know that array being an object in javascript, makes it non-primitive data types, which by default makes it a pass by reference.
Now this is true in most of the used cases I have encountered however the code I am sharing shows a weird behavior which I am not understanding and it seems more like a 'pass by value type'.
var arr = ['a','b','c']
/*
function addArr(ar){
ar.push('d')
return ar
}
console.log(addArr(arr)) // ['a', 'b', 'c', 'd']
console.log(arr) // ['a', 'b', 'c', 'd']
*/
//the above output is expected behavior for an Array object
function changeArr(ar){
console.log(ar) //1-// ['a', 'b', 'c']
ar = ['12','11']
console.log(ar) //2-// ['12', '11']
return ar
}
console.log(changeArr(arr)) //3-// ['12', '11']
console.log(arr) //4-// ['a', 'b', 'c']
//now I expect the forth console output to be ['12','11'] here because it is an object
You are basically re-assinging the object and not modifying the original object.
ar = ['12','11']
That's why Javascript reassigns new value.
Please see the comments.
let arr = [1, 2, 3, 4];
function changeArr(ar) {
//console.log(ar)
ar = ['12', '11'] // creating a new array ie creating a new space in heap putting these values there and storing its reference in ar or assigning it to the reference
//console.log(ar)
return ar
}
function changeArr2(ar) {
ar.push(55); // here we have changed the array that is pointed by the reference stored in ar
return ar
}
console.log(changeArr(arr))
console.log(changeArr2(arr));
console.log(arr) // now the original array contains 55 too
For some more clear picture have a look here-https://stackoverflow.com/a/57852144/7849549
function changeArr(ar){
console.log(ar)
ar = ['12','11'] // <- THIS LINE RIGHT HERE
console.log(ar)
return ar
}
You are creating a new array, not manipulating the old one. Every time you call that function you are creating a new array and returning the new one (if you call that function 5 times you'll get 5 new arrays). The one that you passed as an input is irrelevant and is left unchanged.
EDIT The only relationship between the new array you creating and what you passed as an input is that they use the same variable name inside the closure, so that, inside that closure, you can no longer access both the input and the new array at the same time. But that's a different topic...
Maybe this will make it clearer:
var x = 'something that is not an array'
console.log(changeArr(x));
console.log(x);
And this would perhaps make it clearest of all:
var arr = [1,2,3,4];
console.log(changeArr());
console.log(arr);

Javascript: point-free style in callback

So I wanted the elements of the array arr1 that also happen to belong to the array arr2. I figured arr1.filter(arr2.includes) should do the trick, but it gave me an error (see below). Strangely, though, arr1.filter(x => arr2.incudes(x)) worked fine. Even though the functions arr2.includes and x => arr2.includes(x) aren't referentially equal, shouldn't they take the same values on the same inputs? What am I missing, here?
> arr1 = ['a', 'b', 'c']
[ 'a', 'b', 'c' ]
> arr2 = ['a', 'c', 'd']
[ 'a', 'c', 'd' ]
>
> arr1.filter(x => arr2.includes(x))
[ 'a', 'c' ]
> arr1.filter(arr2.includes)
TypeError: Cannot convert undefined or null to object
at includes (<anonymous>)
at Array.filter (native)
at repl:1:6
... etc ...
There are two reasons you can't just do arr1.filter(arr2.includes):
arr2.includes is just a reference to the function, but what you need is both a reference to the function and to the array that you want to use it on (arr2). You could solve that by using Function.prototype.bind, but:
filter passes its callback multiple arguments, not just one: It passes the value, its index, and the original array. includes will try to use the second argument it receives as the index at which to start searching, so when filter passes it the index, it'll use that and skip leading entries.
So the usual solution is to use a wrapper function that knows it needs to use includes on arr2 and knows to only pass it the one argument — which is what you've done with your arrow function.
But see also Michał Perłakowski's answer for an answer from the functional programming perspective using a utility function to create the callback function rather than creating it inline.
Here's how you could implement an includes function that could be used in point-free style:
const arr1 = ['a', 'b', 'c'];
const arr2 = ['a', 'c', 'd'];
const includes = arr => x => arr.includes(x);
console.log(arr1.filter(includes(arr2)));
If you're interested in functional programming in JavaScript, you should try the Ramda library. With Ramda your code could look like this:
const arr1 = ['a', 'b', 'c'];
const arr2 = ['a', 'c', 'd'];
// First option: R.flip
console.log(R.filter(R.flip(R.contains)(arr1), arr2));
// Second option: R.__ (placeholder argument)
console.log(R.filter(R.contains(R.__, arr1), arr2));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.24.1/ramda.min.js"></script>

delete array using value not index

must I check B is in which index? How can I get rid of B? says I have a function that receive a param that might be A,B,C
let grade = ['A','B','C']
delete grade['B']; // this won't work?
console.log(grade)
If you're really committed to the idea of using the delete operator on an array, you could it as so:
let grade = ['A', 'B', 'C'];
delete grade[grade.indexOf('B')];
Note, however, that this does not accomplish what it is that you likely want to do. More clearly, I assume you'd want the operation above to return ['A', 'C']. It actually does not. Rather, you get an undefined at index 1 (where the value B previously resided).
console.log(grade);
['A', undefined x 1, 'C']
The most appropriate operation to properly displace the B from the array would be to use Array#splice. For example:
let grade = ['A', 'B', 'C'];
grade.splice(grade.indexOf('B'), 1);
console.log(grade);
['A', 'C']

Check if one array is contained in another array

I have
['a', 'b', 'c']
I want to know if this array is contained in this array:
['a', 'b', 'c', 'd']
I know I can do 2 for loops and check item per item, but is there a oneliner for it?
You can do this using Array.prototype.some. This will run the provided function against all the items in an array, and return true if the function returns true for any of them. The following will return true if any items from array are not contained in otherArray, which you can use to determine if one array is fully contained in the other:
return !array.some(function(item) {
return otherArray.indexOf(item) === -1;
});
However, this is not the most elegant solution. The logic can be summed up as:
not any items from array not in other array
Which has far too many negatives. We can instead use Array.prototype.every, which is very similar except it returns true only if all items in an array return true for the provided function. The below is equivalent to what we had before:
return array.every(function(item) {
return otherArray.indexOf(item) !== -1;
});
Except that can be summed up as:
all items in array in other array
Finally, we can implement this as an additional prototype function. Note that the second parameter for every is optional, and sets what this refers to in the function when provided. If we did not pass it in, we would not be able to refer to the this from the outside scope.
Array.prototype.contains = function(array) {
return array.every(function(item) {
return this.indexOf(item) !== -1;
}, this);
}
This can now be used as a one liner in our code:
['a', 'b', 'c'].contains(['a', 'b']) // returns true
If you are able to use ECMAScipt 6, you can use arrow functions to make this a true one-liner.
return array.every(item => otherArray.indexOf(item) !== -1);
ES6 one-lined answer
containedArray.every(element => mainArray.includes(element))
...an improved answer on top of the ES6 suggestion of #James Brierley:
by using every(...) (which returns true if all the elements pass the test we've provided - false otherwise) alongside includes, which IMO is more human-readable - and less error prone - than checking for a index !== -1.
var mainArray = [1, 30, 39, 29, 10, 13];
var containedArray = [1, 30, 39, 29]
console.log(containedArray.every(element => mainArray.includes(element)));

simple string split is returning object instead array

I'm trying a simple string split in NodeJS, but it is returning an object, not array.
var mytext = "a,b,c,d,e,f,g,h,i,j,k";
var arr = mytext.split(",");
console.log(typeof mytext); <======= output string
console.log(typeof arr); <======= output object
jsfiddle: http://jsfiddle.net/f4NnQ/
why?
The output of String.prototype.split is an Array and that is an Object.
console.log(typeof []);
// object
You can confirm that the returned object is an array, like this
console.log(Object.prototype.toString.call(arr));
// [object Array]
console.log(arr);
// [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k' ]
Quoting from the MDN Documentation of String.prototype.split,
The split() method splits a String object into an array of strings by separating the string into substrings.
Arrays are objects in javascript.
If you want to check if its an array -
you can do -
Array.isArray(arr)
Split method always returns an array . Array is an object in javascript. If you want to check whether it is an array use Array.isArray(arr)
An array is an object.
Read about typeof results here
If you output as
console.log(arr);
You will see an array
var mytext = "a,b,c,d,e,f,g,h,i,j,k";
var arr = mytext.split(",");
console.log(typeof mytext); <======= output string
console.log(arr); `this will return object`
for(i=0;i<=10; i++){
console.log(arr[i]);
}

Categories