I am now writing a javascript to filter out arrays that contains a specific sub-array. Of course I can write the function by myself, but I am just curious if there are already some built-in function in javascript or other javascript library to do that, or if there are easy way to do that with just a few lines.
I found that I can use underscore.js if all the elements in the sub-array is unique. There is a intersection function and I can check the lenght after intersection to see if the length are correct. However, that function fails if there are repeated values in the sub-array.
For example,
_.intersection([1, 2, 3, 4, 5], [2, 1]);
This will return [1, 2] and by checking the length I will know this array contains the sub-array.
However, when there are repeated values in the sub-array,
_.intersection([1, 1, 2, 3, 4, 7, 10], [1, 1, 2]);
_.intersection([1, 2, 3, 4], [1, 1, 2]);
Both will return [1, 2] and the cases cannot be distinguished.
Is there other pre-built function I can use or is there a easy way to do the job within a few lines?
Try this:
function contains(a, b) {
// sort arguments
if(a.length < b.length) {
var temp = a;
a = b;
b = temp;
}
// copy array
a = a.slice();
return b.every(function(elm) {
var index = a.indexOf(elm);
if(index !== -1) {
// remove the found element
a.splice(index, 1);
return true;
}
return false;
});
}
console.log(contains([1, 1, 2], [1, 2, 3, 4, 7, 10])); // logs false
console.log(contains([1, 1, 2], [1, 1, 2, 3, 4, 7, 10])); // logs true
console.log(contains([1, 2, 3, 4, 7, 10], [1, 1, 2])); // logs false
console.log(contains([1, 1, 2, 3, 4, 7, 10], [1, 1, 2])); // logs true
Here is the demo
Related
With an array of: [1, 2, 3, 4, 5, 6]
I would like to delete between 2 indices such as 2 and 4 to produce [1, 2, null, null, 5, 6]. What's the easiest way to do this?
Hopefully better than this:
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
let i = 2;
const rangeEnd = 9;
while (i < rangeEnd) {
delete array[i];
i++;
}
console.log(array)
If you want to use some native API you can actually do this with splice(). Otherwise, you should iterate a for loop through your array and change the value in each iteration.
Here is an example of how it would be done:
const array = [1, 2, 3, 4, 5, 6]
array.splice(3, 2, null, null) // the First element is beginning index and the second is count one will indicate how many indexes you need to traverse from the first one, then you should provide replace element for each of them.
console.log(array)
Note: For more info about it you can read more here.
There is a possible workaround for large scale replacement, so I will give it a touch here:
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var anotherArr = Array(2).fill(null); // or you can simply define [null, null, ...]
Array.prototype.splice.apply(arr, [3, anotherArr.length].concat(anotherArr));
console.log(arr);
As you mean the range (2, 4] so you can follow this:
The range is: lower limit exclusive and the upper limit inclusive.
const arr = [1, 2, 3, 4, 5, 6];
const deleteRange = (arr, f, t) => {
return arr.map((item, i) => {
if (i + 1 > f && i + 1 <= t) {
return null;
}
return item;
})
}
console.log(deleteRange(arr, 2, 4));
I start by pointing out that this code works. That is not the problem! I just don't understand how really. As I understand it the chunked.push method ads a new array all the time. But obviously, it does not. It gives the right answer:
[[ 1, 2], [3, 4], [5]]
I simply do not understand what is happening in this code. It spits out the right answer and put several items in each array if necessary but the code creates a new subarray each time, no? No, obviously not - but I don't understand why not? Please help!
function chunk(array, size) {
let workArr = [...array];
let chunked = [];
for (let i = 0; i < workArr.length; i++) {
let last = chunked[chunked.length - 1];
if (!last || last.length === size) {
chunked.push([workArr[i]])
} else {
last.push(workArr[i]);
}
}
return chunked;
}
Here is examples of some input parameters and expected results:
// chunk([1, 2, 3, 4], 2) --> [[ 1, 2], [3, 4]]
// chunk([1, 2, 3, 4, 5], 2) --> [[ 1, 2], [3, 4], [5]]
// chunk([1, 2, 3, 4, 5, 6, 7, 8], 3) --> [[ 1, 2, 3], [4, 5, 6], [7, 8]]
// chunk([1, 2, 3, 4, 5], 4) --> [[ 1, 2, 3, 4], [5]]
// chunk([1, 2, 3, 4, 5], 10) --> [[ 1, 2, 3, 4, 5]]
Let's break it
This copies an array there is used a spread operator
let workArr = [...array];
Iterate over every item in workArr array
for (let i = 0; i < workArr.length; i++) {
}
I think this would give you undefined at first run, because there is nothing at index -1 in chunked (because at first, chunked.length is 0), but it will set last to last element of chunked array
let last = chunked[chunked.length - 1];
If last has falsey value (0, null, undefined, "", NaN, false) or length of last equals to size (be aware, that last should be array or string), then push i-th element (indexing from 0) of workArr array into chunked array as an array, else push that element from workArr into last, but last then should be an array
if (!last || last.length === size) {
chunked.push([workArr[i]])
} else {
last.push(workArr[i]);
}
then simply return chunked array
return chunked;
This is kind of confusing so I will just demonstrate. I would like to create a function that takes an array like this:
[1, 2, 3, 4, 5, 6, 7]
...and returns an array of arrays like this:
[[1, 5], [2, 6], [3, 7], [4]]
assuming that the user wanted 4 groups. Notice that the elements are added to each group before 5th element is added back to the first.
Is there a simple way to do this? My project is using webpack, so I am open to ES6+ or even lodash. Thanks!
My proposal is:
var numGroups= 4;
var result = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].reduce(function(acc, ele, idx) {
var i = idx % numGroups;
(acc[i] == undefined) ? acc[i] = [ele] : acc[i].push(ele);
return acc;
}, []);
console.log(result);
Below are several stabs at removing 3 from the array [8,2,3,4] using lodash. The elegant syntax for removing an object from an array of objects makes me wonder if I just haven't figured out the right approach here.
> _.remove([8,2,3,4], 3)
[]
> x = [8,2,3,4]
[8, 2, 3, 4]
> _.remove(x, 3)
[]
> x
[8, 2, 3, 4]
> _.remove(x, {3: true})
[]
> x
[8, 2, 3, 4]
> _.remove(x, [3])
[]
> x
[8, 2, 3, 4]
> _.remove(x, function(val) { return val === 3; });
[3]
> x
[8, 2, 4]
Is there another way to remove a matching element from an array that would be similar to _.remove(arrayOfObjs, {id:3})
Yes, but not using remove. You can instead use pull to remove values from an array:
Removes all provided values from array using SameValueZero for equality comparisons.
// pull modifies its argument:
x = [8, 2, 3, 4]
_.pull(x, 3)
x // => [8, 2, 4]
// pull also returns the modified array:
y = _.pull([1, 2, 3, 4, 5], 2, 3) // => [1, 4, 5]
I have an array and would like to sort all but the last n elements.
For example, if the array is 10 elements long, would like elements 0 through 7 to be sorted while elements 8-9 are left in place.
var array = [5, 2, 6, 4, 1, 9, 3, 8, 7];
array = array.slice(0, 7).sort().concat(array.slice(7, 10));
// array is now [1, 2, 3, 4, 5, 6, 9, 8, 7]
If you need to sort the array in place (i.e. without creating a new, sorted array), which is what the sort() method does, you could do the following:
var array = [5, 2, 6, 4, 0, 1, 9, 3, 8, 7];
var unsorted = array.slice(7);
array.length = 7;
array.sort().push.apply(array, unsorted);
More generally, here's a function to sort a portion of an array in place. Like the sort() method, it also returns a reference to the array.
function partialSort(arr, start, end) {
var preSorted = arr.slice(0, start), postSorted = arr.slice(end);
var sorted = arr.slice(start, end).sort();
arr.length = 0;
arr.push.apply(arr, preSorted.concat(sorted).concat(postSorted));
return arr;
}
Example:
var array = [5, 2, 6, 4, 0, 1, 9, 3, 8, 7];
partialSort(array, 0, 7);
An ES6 riff on the solution provided by #darin
let subSort = (arr, i, n, sortFx) => [].concat(...arr.slice(0, i), ...arr.slice(i, i + n).sort(sortFx), ...arr.slice(i + n, arr.length));
i is the index where the subsection begins
n is the number of elements to sort
sortFx is the sorting function
So it's possible to sort a range within an array:
var array = [5, 2, 6, 4, 1, 9, 3, 8, 7];
// sort array beginning at index 2; sort 4 elements of array
subSort(array, 2, 4, (a, b) => a - b);
// array is now [5, 2, 1, 4, 6, 9, 3, 8, 7]
subSort(array, 2, 4, (a, b) => b - a);
// array is now [5, 2, 9, 6, 4, 1, 3, 8, 7]
subSort() can be used for objects of arbitrary complexity.
let arr = [2, 1, 5, 4, 3];
arr = [...arr.slice(0, 2), ...arr.slice(2).sort((a, b) => a - b)];
After sorting a sub-array the original array will be [2, 1, 3, 4, 5]