delete array using value not index - javascript

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']

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);

Quickest/most elegant way to verify a 2D array has same length per row?

Let's say I have a 2D array:
const matrixRegular = [
['a', 'b', 'c'],
['e', 'f', 'g'],
];
Let's say I want to verify that every row in this matrix has the same length, so the example above is a valid matrix, but the example below is not:
const matrixIrregular = [
['a', 'b', 'c'],
['e', 'f']
];
What's a clean/elegant way of doing it? This is the one-liner I have:
const isRegularMatrix = matrix => new Set(data.map(row => row.length)).size === 1
Convert the matrix to an array of just row length, then use Set to ensure every element is a duplicate (same length), hence it comes out with size 1.
You can use every() and compare length of each array with the length of the first.
const isRegularMatrix = matrix => matrix.every(x => x.length === matrix[0].length)

Terse way to get remainder of an iterable (like an array)

I want to get the remainder of an iterable like an array. Like so:
var arr = ['a', 'b', 'c'];
var brr = arr.slice(1);
But is there a terser way (maybe using destructuring assignment?).
Yes there is:
var [,...brr] = arr; // ['b', 'c']
Multiple elision also works:
var [,,...brr] = arr; // ['c']

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>

Lodash remove from string array

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"]

Categories