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']
Related
Is it possible to filter an array with multiple values with liner time O(N) the current example should be O(n^{2}), is it possible to run it faster? (In real world app I will have thousands of elements).
Could you point me out in the right direction?
const data = ['a', 'b', 'c', 'd'];
const filterBy = ['c', 'a'];
const r = data.filter(x => filterBy.includes(x));
console.log(r);
yes it is possible.
you can use hash set which will provide you lookup of an element in O(1) (on average) instead of the filterBy array.
example:
const data = ['a', 'b', 'c', 'd'];
const filterBy = ['c', 'a'];
const filterBySet = new Set(filterBy)
const r = data.filter(x => filterBySet.has(x));
console.log(r);
I tried the following code to view the data structure of Iterator object. It just prints object { }
var array1 = ['a', 'b', 'c'];
var iterator = array1.keys();
console.log(iterator); // object { }
console.log(iterator.toString()); // "[object Array Iterator]"
You can use spread operator (...) for this. What it does is, it allows an iterable such as an array expression or string to be expanded.
Read more about spread syntax here
Something like
var array1 = ['a', 'b', 'c'];
var iterator = array1.keys();
console.log(...iterator);
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>
I am going through a lesson on Javascript Arrays where we have to understand certain what is under the hood of underscoreJS methods. I need to write a function for the _.each method which will allow me to iterate over a single array and return a modified nested array that includes the index for each value.
For example:
var myArray = ['a', 'b', 'c'];
after the method each is called on myArray the new array should look like:
myArray = [ [ 'a', 0 ], [ 'b', 1 ], [ 'c', 2 ] ];
I have been searching on google for a day and have not found anything specific to this task. Stuck and need some help! Thank you.
_.each iterates over your array and has the following signature
function(value, index, array)
So lets see how it could be done ...
var result = [];
_.each(myArray, function(value, index, array){
result.push([value, index]); // <= does the work
}
This is not the ideal way (you should use map) but does illustrate how the each works.
Good luck
You can do it like below by using Array.prototype.reduce() function,
var myArray = ['a', 'b', 'c'];
var result = myArray.reduce(function(a,b,i){
return (a.push([b,i]), a)
},[]);
console.log(result); // [['a',0],['b',1],['c',2]];
Or as #bergi said you can do it with Array.prototype.map() also,
var myArray = ['a', 'b', 'c'];
var result = myArray.map(function(itm,i){
return [itm,i];
});
console.log(result); // [['a',0],['b',1],['c',2]];
Just use Array#map():
The map() method creates a new array with the results of calling a provided function on every element in this array.
var myArray = ['a', 'b', 'c'],
result = myArray.map(function (a, i) {
return [a, i];
});
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
If you're learning _.each method, you can do it like this
var myArray = ['a', 'b', 'c'];
_.each(myArray, function (e, i) {
myArray[i] = [e, i];
});
document.write(JSON.stringify(myArray));
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
But for your case better to use _.map function
I'm basically using $all operator in mongo and the input i get might be array or single element as following. So how do use underscore to put all the elements in one array and then
userId = 'a';
userIds = ['a', 'b', 'c'];
otherId = ['a'] or 'a';
searchArray = [userId, userIds, otherId]
db.collections.find({userIds: {$all: searchArray}})
You can use union as long as they are arrays.
_.union(arrays)
var userId = ['a'],
userIds = ['a', 'b', 'c'];
otherId = ['a'],
searchArray = _.union(userId, userIds, otherId);
If all variables aren't promised to be arrays, you probably want the flatten method.
userId = 'a'; // strings
userIds = ['a', 'b', ['c']]; // multidimensional array
otherId = ['a']; // single dimensional array
searchArray = _.flatten([userId, userIds, otherId]);
db.collections.find({userIds: {$all: searchArray}})
No need for underscore, you can use concat:
var userId = ['a'],
userIds = ['a', 'b', 'c'],
otherId = ['a'];
var arr = userId.concat(userIds, otherId)
This will work even if one of those is not an array but just a number or string. Working example here:
http://codepen.io/anon/pen/qbNQLw