Can anyone explain "slice" behavior?
var arr = ['a', 'b', 'c', 'd', 'e', 'f']
console.log(arr.slice(0, 4)); // [ 'a', 'b', 'c', 'd' ]
console.log(arr.slice(4, 4)); // []
Why the second array is empty? Should not it be ['e','f'] ?
If omit "end" param, the result as expected.
arr.slice(4, 4) will return the items beginning at index = 4 to index = 4; 4-4=0 so your array has got a length of 0
https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Array/slice
var arr = ['a', 'b', 'c', 'd', 'e', 'f']
console.log(arr.slice(0, 4)); // [ 'a', 'b', 'c', 'd' ]
console.log(arr.slice(4, 4)); // []
console.log(arr.slice(2, 4));
console.log(arr.slice(1, 2));
According to official docs it:
Returns a shallow copy of a portion of an array into a new array object selected from begin to end (end not included). The original array will not be modified.
Meaning that, you start at the index 4 and u end at that index, so literally you took no elements since the difference between start and end index is 0, so no elements are taken.
Related
I've got array of variables and next variable which I want to add alphabetically. It goes A-Z and after that AA, AB, AC etc..
so in when next variable is E I want to add it at the end of letters with length=1, if next variable would be AC I'd add it at the end on letters with length=2 etc. I tried to do it with findIndex, but it returns the first occurrence, not the last one and lastIndexOf accepts value while in my case it should be the last element with given length.
let variables = ['A', 'B', 'C', 'D', 'AA', 'AB'];
const nextVariable = 'E';
const idx = variables.findIndex(x => x.length === nextVariable.length);
variables.splice(idx, 0, nextVariable);
console.log(variables);
// should be ['A', 'B', 'C', 'D', 'E', 'AA', 'AB']
You can just look for the first variable which is longer than the variable to insert, and if it doesn't exist (findIndex returns -1), add to the end of the array:
let variables = ['A', 'B', 'C', 'D', 'AA', 'AB'];
let nextVariable = 'E';
let idx = variables.findIndex(x => x.length > nextVariable.length);
variables.splice(idx < 0 ? variables.length : idx, 0, nextVariable);
// should be ['A', 'B', 'C', 'D', 'E', 'AA', 'AB']
console.log(variables);
nextVariable = 'AC';
idx = variables.findIndex(x => x.length > nextVariable.length);
variables.splice(idx < 0 ? variables.length : idx, 0, nextVariable);
// should be ['A', 'B', 'C', 'D', 'E', 'AA', 'AB', 'AC']
console.log(variables);
let variables = ['A', 'B', 'C', 'D', 'AA', 'AB'];
const nextVariable = 'E';
variables[variables.length] = nextVariable
variables = variables.sort((x,y) => x.length<y.length ? -1 : x.length==y.length ? x.localeCompare(y) : 1)
console.log(variables);
You can use a custom sort function and test the alphabetical order and length of each value.
function mySort(a, b) {
if(a.length == b.length) {
return a.localeCompare(b);
} else {
return a.length - b.length;
}
}
The you can use this function to sort the array after a new value has been added:
variables.sort(mySort);
Consider the following arrays:
['a', 'b', 'a'] //method should return true
['a', 'b', 'c'] //method should return true
['a', 'c', 'c'] //method should return false
I want to write a method that most efficiently checks to see if both 'a' and 'b' exist in the array. I know I can do this in a simple for loop
let a_counter = 0;
let b_counter = 0;
for (let i = 0; i < array.length; i++) {
if (array[i] === 'a') {
a_counter++;
}
if (array[i] === 'b') {
b_counter++;
}
}
return (a_counter > 0 && b_counter > 0);
But this isn't very short. I can do indexOf but that will loop through twice. I have also considered using a set as below:
const letter_set = new Set(array)
return (letter_set.has('a') && letter_set.has('b'))
But I am pretty unfamiliar with sets and don't know if this solution could potentially be more expensive than just looping. I know that has() operations should be faster than array iterations but constructing the set probably takes at least O(N) time (I'm assuming).
Is there a clean and efficient way to find multiple elements in an array? ES6 answers welcome
You can use every and includes to do this check.
So we are saying every item must be included in the array.
function contains(arr, ...items) {
return items.every(i => arr.includes(i))
}
console.log(contains(['a', 'b', 'a'], 'a', 'b'))
console.log(contains(['a', 'c', 'c'], 'a', 'b'))
console.log(contains(['a', 'b', 'c'], 'a', 'b', 'c'))
console.log(contains(['a', 'b', 'c', 'd'], 'a', 'b', 'c', 'd', 'e'))
You could use just the Set and check if the wanted items are in the items array.
const
check = (items, wanted) => wanted.every(Set.prototype.has, new Set(items));
console.log(check(['a', 'b', 'a'], ['a', 'b'])); // true
console.log(check(['a', 'b', 'c'], ['a', 'b'])); // true
console.log(check(['a', 'c', 'c'], ['a', 'b'])); // false
array.includes('a') && array.includes('b')
includes seems like a real handy way to check for specific elements, even if there is more than one.
Not as compact as the other examples, but it does do the job in single run.
const arr1 = ['a', 'b', 'a']; //method should return true
const arr2 = ['a', 'c', 'c']; //method should return false
const arr3 = ['a', 'b', 'c']; //method should return true
const reducer = ({ a, b }, char) => ({
a: a || char === 'a',
b: b || char === 'b'
});
const includesAnB = arr => {
const { a, b } = arr.reduce(reducer, {});
return a && b;
}
console.log(includesAnB(arr1));
console.log(includesAnB(arr2));
console.log(includesAnB(arr3));
I have this multidimensional array:
points= [['1','2','3'], ['4','5','6'] ]
and i have this array of points needed for a check in the above array;
new_points = [ 'a','b', 'c', 'd', 'e', 'f']
So a goes to 1 (0,0) , b to 2 (0,1) etc so points becomes;
points= [['a','b','c'], ['d','e','f'] ]
the multi-dimension array will always be 3 by 3, 4 by 4 etc.
Use two .map() and in nested function get index of relevant item of new_points based on map index.
var points= [['1','2','3'], ['4','5','6']];
var new_points = [ 'a','b', 'c', 'd', 'e', 'f'];
var newArr = points.map(function(item, i){
return item.map(function(val, j){
return new_points[(item.length*i)+j];
});
});
console.log(newArr);
If points is 2 dimensional but the nested array can be of variable length then you can reduce points using a counter to help get the item from new_points:
const points = [[1], [2, 3]];
const new_points = ['a', 'b', 'c'];
const createNewPoints = (points, new_points) =>
points.reduce(
([result, counter], items) => [
result.concat([
items.map((_, i) => new_points[i + counter]),
]),
counter + items.length,
],
[[], 0],
)[0];
console.log(createNewPoints(points, new_points));
You could shift each element of new_points by mapping the original array structure.
var points = [['1', '2', '3'], ['4', '5', '6']],
new_points = ['a', 'b', 'c', 'd', 'e', 'f'];
points = points.map(a => a.map(Array.prototype.shift, new_points));
console.log(points);
I have an Object containing multiple arrays like this
someObj = {
array1:['a', 'b'],
array2:['a', 'b', 'c'],
array3:['a', 'b', 'c', 'd']
}
Is there any built-in method or property in JS/ES6 which returns the largest array or length of the largest array? Please suggest
You can use Array.prototype.reduce and check the value of accumulator with the array length.
Use Object.values() to get all the values of the array.
var someObj = {
array1:['a', 'b'],
array2:['a', 'b', 'c'],
array3:['a', 'b', 'c', 'd'],
array4:['a', 'b', 'c']
}
var maxLength = Object.values(someObj).reduce((a,e) => { return a > e.length ? a:e.length}, 0);
console.log(maxLength);
You can use Object.values to get all of the values for any object. Here's a neat oneshot which will return the longest list in combination with reduce:
const longestList = Object.values(someObj)
.reduce((longest, list) => list.length > longest.length ? list : longest)
Object.values: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/values
reduce: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
You can simply use a for loop and iterate through it comparing the length of the arrays.
var someObj = {
array1:['a', 'b'],
array2:['a', 'b', 'c'],
array3:['a', 'b', 'c', 'd']
}
var max=0;
for(x in someObj){
someObj[x].length > max ? max=someObj[x].length : max;
}
console.log(max);
I've found a lot of posts that solve this problem:
Assuming we have:
array1 = ['A', 'B', 'C', 'D', 'E']; array2 = ['C', 'E'];
Is there a proven and fast solution to compare two arrays against each other, returning one array without the values appearing in both arrays (C and E here). Desired solution:
array3 = ['A', 'B', 'D']
But what if you have:
array1 = ['A', 'B', 'C', 'D', 'D', 'E']; array2 = ['D', 'E'];
and you're looking for the solution to be:
array3 = ['A', 'B', 'C', 'D'] // don't wipe out both D's
Here is some context:
You are trying to teach students about how sentences work. You give them a scrambled sentence:
ate -- cat -- mouse -- the -- the
They start typing an answer: The cat
You would like the prompt to now read:
ate -- mouse - the
At present, my code takes out both the's.
Here is what I've tried:
(zsentence is a copy of xsentence that will get manipulated by the code below, join()ed and put to screen)
for (i=0; i < answer_split.length; i++) {
for (j=0; j < xsentence.length; j++) {
(function(){
if (answer_split[i] == xsentence[j]) { zsentence.splice(j,1); return; }
})();
}
}
Just iterate over the array of elements you want to remove.
var array1 = ['A', 'B', 'C', 'D', 'D', 'E'];
var array2 = ['D', 'E'];
var index;
for (var i=0; i<array2.length; i++) {
index = array1.indexOf(array2[i]);
if (index > -1) {
array1.splice(index, 1);
}
}
It's O(array1.length * array2.length) but for reasonably small arrays and on modern hardware this shouldn't remotely cause an issue.
http://jsfiddle.net/mattball/puz7q/
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/splice
You can use Filter also.
Please review below example.
var item = [2,3,4,5];
var oldItems = [2,3,6,8,9];
oldItems = oldItems.filter(n=>!item.includes(n))
so this will return [6,8,9]
and if you want to get only matched items then you have to write below code.
oldItems = oldItems.filter(n=>item.includes(n))
This will return [2,3] only.