I have an array of items, can be objects with many properties, and I want to group some of these items based on order:
example:
[a,b,c,d,e] => [a,[b,c,d],e]
must group (b, c, d) or (a) or (b, c) or (all)
must not group (a, c) or (a, d) for example because they are not sequential
Some possibilites:
[a,b,c,d] to [[a,b,c,d]]
[a,b,c,d] to [[a],b,c,d]
[a,b,c,d] to [[a,b],c,d]
[a,b,c,d] to [[a,b,c],d]
[a,b,c,d] to [a,b,[c,d]]
always sequential items
think of item a like an object with index;
If I understand correctly, you want to group n sequential elements of the array starting from an index ind and put that that group back into the array at the same index. You can acheive that using splice:
function group(arr, ind, n) {
var g = arr.splice(ind, n); // cut out n elements from the array at index ind
arr.splice(ind, 0, g); // push back those cut-out elements into the same index ind (the elements are in array because of the first slpice call)
}
var arr = [1, 2, 3, 4, 5, 6];
group(arr, 2, 3);
console.log(arr); // [1, 2, [3, 4, 5], 6]
EDIT:
As requested, changing group to create a new array instead of altering the original and taking start and end indexes. So for that we are going to use slice/concat instead of splice:
function group(arr, start, end) {
return [].concat(arr.slice(0, start), [arr.slice(start, end + 1)], arr.slice(end + 1));
}
var arr = [1, 2, 3, 4, 5, 6];
console.log(group(arr, 2, 3)); // => [1, 2, [3, 4, 5], 6]
console.log(group(arr, 4, 6)); // => [1, 2, 3, 4, [5, 6]]
console.log(group(arr, 0, 3)); // => [[1, 2, 3, 4], 5, 6]
which concatinate the subarrays: from 0 to start, from start to end + 1 (put in an array of its own so its stays grouped) and from end + 1 onward. If you want the end index to be exclusive (the element at end not included) then just change end + 1 to end.
Based on the more recent comments you may be looking for Array's own, built-in slice method, it provides a continuous sub-region of an array, where start and end positions are its arguments:
function format(a){return "["+a.join(",")+"]";}
var arr=['a','b','c','d','e'];
console.log("original: "+format(arr));
console.log("slice(0,1): "+format(arr.slice(0,1)));
console.log("slice(0,2): "+format(arr.slice(0,2)));
console.log("slice(1,4): "+format(arr.slice(1,4)));
console.log("slice(2,4): "+format(arr.slice(2,4)));
console.log("slice(2,2): "+format(arr.slice(2,2)));
Note 1: The second argument is the position of the "last+1" element you want, it is best seen in the last example where slice(2,2) provides an empty array
Note 2: format is just about getting array contents in one line, console.log(somearray) displays the elements vertically.
Then of course you can do whatever you need, but it is definitely worth to note that this function exists and it is built-in.
Like building the array-in-array thing you describe:
function format(a){var s="[",first=true;a.forEach(function(i){
if(first)first=false;else s+=",";s+=i instanceof Array?format(i):i;});
s+="]";return s;}
function group(arr,begin,end){
var ret=[];
for(var i=0;i<begin;i++)ret.push(arr[i]);
ret.push(arr.slice(begin,end));
for(var i=end;i<arr.length;i++)ret.push(arr[i]);
return ret;
}
var arr=['a','b','c','d','e'];
console.log("original: "+format(arr));
console.log("group(arr,0,1): "+format(group(arr,0,1)));
console.log("group(arr,0,2): "+format(group(arr,0,2)));
console.log("group(arr,1,4): "+format(group(arr,1,4)));
console.log("group(arr,2,4): "+format(group(arr,2,4)));
console.log("group(arr,2,2): "+format(group(arr,2,2)));
Examples are the same as for the slice-explanation, including the empty array in the last one (with 2,2). It is up to you if you want such empty element (as kind of a 'cursor') or not.
And of course the thing also works with the nested loops in my original answer, if you want to generate all possible selections from an array - that is how your question initially seemed to me:
function format(a){var s="[",first=true;a.forEach(function(i){
if(first)first=false;else s+=",";s+=i instanceof Array?format(i):i;});
s+="]";return s;}
function group(arr,begin,end){
var ret=[];
for(var i=0;i<begin;i++)ret.push(arr[i]);
ret.push(arr.slice(begin,end));
for(var i=end;i<arr.length;i++)ret.push(arr[i]);
return ret;
}
var arr=['a','b','c','d','e'];
console.log("original: "+format(arr));
for(var i=0;i<arr.length;i++)
for(var j=i+1;j<=arr.length;j++){
console.log(format(group(arr,i,j)));
}
Related
//code1
let a= [1, 3 , 4, 6];
[7, 8 , 9].forEach(l => a.push(l));
console.log(a);
// [1, 3, 4, 6, 7, 8, 9 ]
1.it worked for push() function
//code2
let a= [1, 3 , 4, 6];
a.forEach(l => a.pop(l));
console.log(a);
//[ 1, 3 ]
2. didn't work for pop() though
Javascript Array.pop() removes the last element from the array and returns that.
Example:
var arr = [1,2,3]
arr.pop(); // returns 3
Reference
If you want to remove a element with specific value than try something like:
var arr = [1, 2, 3];
var index = arr.indexOf(1);
if (index > -1) {
array.splice(index, 1);
}
var arr = [1, 2, 3, 4];
console.log(arr.pop());
var index = arr.indexOf(2);
if (index > -1) {
arr.splice(index, 1);
}
console.log(arr)
forEach automatically extracts the elements one by one and gives them to you
It starts from the beginning of the array, and does them all.
It doesn't delete elements from the array.
a = [1, 3, 4, 6];
a.forEach(item => console.log(item));
// output is in forwards order
// and 'a' retains original contents
pop() extracts and deletes one element for you
It starts from the end of the array, and does only one.
It deletes the element from the array.
a = [1, 3, 4, 6];
while (a.length > 0) {
console.log(a.pop())
}
// items come out in reverse order
// and 'a' is being emptied so it is [] at the end
Choose your method
Do you want the last element actually removed from the array? This is what you would want if you were implementing a stack, for example. In that case, use ".pop()".
This gets one element from the end of the array and deletes it from the array.
Or do you want to just look at each element in turn from the array (starting at the beginning), without changing the array itself. This is a commoner situation. In this case, use ".forEach"
I'm trying to understand the following solution for finding the largest adjacent product in any given array.
Example:
For inputArray = [3, 6, -2, -5, 7, 3], the output should be
adjacentElementsProduct(inputArray) = 21.
7 and 3 produce the largest product.
Possible solution in JS:
function adjacentElementsProduct(arr) {
return Math.max(...arr.slice(1).map((x,i)=>[x*arr[i]]))
}
I am having a hard time understanding two things:
What do the three dots exactly do and how does this get passed into the function? Is there any way to write this in a more understandable way? I know that is the "spread syntax" feature in ES6, but still don't understand completely.
Why do we insert "1" as argument to slice? My first though was to input "0", because we want to start at the start, then loop through everything, and see which adjacent product is the largest.
I'd appreciate any advice, links and explanations.
Thanks.
Cheers!
1. What do the three dots exactly do and how does this get passed into the function? Is there any way to write this in a more understandable way? I know that is some kind of "spread" feature in ES6, but still don't understand completely.
The Math#max needs a list of numbers as parameters, and map produces an array. The spread syntax is used to convert an array to be expanded to a list of parameters.
const arr = [1, 2, 3];
console.log('max on array', Math.max(arr));
console.log('max on list of parameters', Math.max(...arr));
In this case you can use Function#apply to convert the array to a list of parameters. I find it less readable, however.
const arr = [1, 2, 3];
console.log(Math.max.apply(Math, arr));
2. Why do we insert "1" as argument to slice? My first though was to input "0", because we want to start at the start, then loop through everything, and see which adjacent product is the largest.
Lets break down the iteration order of the 2 arrays.
[3, 6, -2, -5, 7, 3] // inputArray
[6, -2, -5, 7, 3] // inputArray.slice(1)
Now on each iteration of inputArray.slice(1):
x: 6, i = 0, arr[0] = 3
x: -2, i = 1, arr[1] = 6
x: -5, i = 2, arr[2] = -2
Since the inputArray.slice(1) array starts from the 2nd element of the inputArray, the index (i) points to the 1st element of the inputArray. And the result is an array of products of 2 adjacent numbers.
var biggestProduct = inputArray[0] * inputArray[1];
for (i=0; i<inputArray.length-1 ; ++i)
{
console.log(biggestProduct)
if ((inputArray[i] * inputArray[i+1] ) > biggestProduct)
{
biggestProduct = inputArray[i] * inputArray[i+1]
}
}
return biggestProduct;
Note: I've declared a variable that consists of 2 input arrays with index number then starts a for loop that indicates input array with his index number, so by that he will go throw all the index number of the array (one of them raised by one so that they won't be at the same value). and at the end of the code, you have the if statement.
You may simply do as follows;
function getNeigboringMaxProduct([x,...xs], r = -Infinity){
var p = x * xs[0];
return xs.length ? getNeigboringMaxProduct(xs, p > r ? p : r)
: r;
}
var arr = [3, 6, -2, -5, 7, 3],
res = getNeigboringMaxProduct(arr);
console.log(res);
I'm trying to write a function that continually adds together the first and last elements of an array using forEach with array.shift() + array.pop().
The problem is that the for-loop doesn't complete the innermost numbers, and so the array is always left with 2 values inside of it.
Code:
function choreAssignment(chores) {
chores.sort(function(a, b) {return a - b});
var assignment = [];
chores.forEach(function() {
assignment.push((chores.pop() + chores.shift()));
});
return assignment.sort(function(a, b) {return a - b});
}
The above code works as expected, but it leaves the innermost two values inside the chores array.
For example if I run:
Code:
var arr = [1, 4, 7, 2, 5, 9, 4, 3];
choreAssignment(arr);
I get:
[8, 9, 10]
Ie, it adds 9 & 1, 7 & 2, 5 & 3, but it leaves [4, 4] inside the array.
I'm not sure why this is. Thank you.
Try changing the forEach to:
while (chores.length) {
assignment.push((chores.pop() + chores.shift()));
}
Note this assumes there are always an even number of elements in array
Instructions:
Write a function called getAllElementsButLast.
Given an array, getAllElementsButLast returns an array with all the elements but the last.
Below is my code that will not pass the requirements for the question. I am not sure why this is not correct even though I am getting back all the elements besides the last.
var arr = [1, 2, 3, 4]
function getAllElementsButLast(array) {
return arr.splice(0, arr.length - 1)
}
getAllElementsButLast(arr) // [1, 2, 3]
I think the reason why it's not accepted is because with splice() you change the input array. And that's not what you want. Instead use slice(). This method doesn't change the input array.
var arr = [1, 2, 3, 4]
function getAllElementsButLast(array) {
var newArr = array.slice(0, array.length - 1);
return newArr;
}
var r = getAllElementsButLast(arr);
console.log(r);
console.log(arr);
This question already has answers here:
Get all non-unique values (i.e.: duplicate/more than one occurrence) in an array
(97 answers)
Closed 6 years ago.
There is a javascript array
var arr = [0, 1, 2, 2, 3, 3, 5];
I want to choose elements that repeats twice. In this case its 2 and 3. and i want attach them into a variable.
var a = 2, b = 3;
As far as i know there is no built-in function to do that job. How can i do that. Thanks.
You can use filter to get the values that occur twice.
var arr = [0, 1, 2, 2, 3, 3, 5];
var dups = arr.filter ( (v,i,a) => a.indexOf(v) < i );
console.log(dups);
In comments you stated you would only have doubles, but no values that occur more than twice. Note that the above would return a value more than once, if the latter would be the case.
This returns the values in an array, which is how you should work. To put them in separate values can be done as follows:
var [a, b, ...others] = dups;
...but you would have to know how many variables to reserve for that, and it does not make your further program any easier. JavaScript has many nice functions (methods) for arrays, so you should in fact leave them in an array.
There is no built in function to do that indeed.
You will have to loop thought the array and keeping track of the number of occurrences of the elements, while building a response array.
You could filter a sorted array.
var arr = [0, 1, 2, 2, 3, 3, 5],
repeats = arr.filter(function (a, i, aa) {
return aa[i - 1] === a;
});
console.log(repeats);
Most simple way to do this is the following:
var dups = [];
var arr = [0, 1, 2, 2, 3, 3, 5];
arr.forEach(function (v, i, a){
delete arr[i];
if (arr.indexOf(v) !== -1){
dups.push(v);
}
});
console.log(dups);
It's destructive however.