How to do a consecutive subarrays in JavaScript [duplicate] - javascript

This question already has answers here:
Split array into chunks
(73 answers)
Closed 20 days ago.
I am studying algorithms in JavaScript; I am trying to generate consecutive subarrays but I don't know to do it.
I have the following array:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
I want to split it in subarrays of size 3 using iteration:
[1, 2, 3] [4, 5, 6] [7, 8, 9]
I know how to do a subarray using slice(), but as I told I want to do consecutive subarrays with size k.
function ub(a) {
let resposta = []
for (let i = 0 ; i < a.length; i++) {
resposta = a.slice(2, 5)
}
return resposta
}
console.log(ub([2, 37, 8, 9, 23, 34, 44]))

Increment the index by the subarray size each time, then slice that number of elements from the current index on each iteration.
function ub(arr, k) {
let res = [];
for (let i = 0; i < arr.length; i += k) res.push(arr.slice(i, i + k));
return res;
}
console.log(JSON.stringify(ub([1,2,3,4,5,6,7,8,9], 3)));

You can use this way
function ub(a) {
return a.reduce((acc, val, index) => {
if (index % 3 === 0) {
acc.push(a.slice(index, index + 3));
}
return acc;
}, []);
}
console.log(JSON.stringify(ub([1, 2, 3, 4, 5, 6, 7, 8, 9])));
or you can use Array.from
function ub(a) {
return Array.from({ length: Math.ceil(a.length / 3) }, (_, i) =>
a.slice(i * 3, i * 3 + 3)
);
}
console.log(JSON.stringify(ub([1, 2, 3, 4, 5, 6, 7, 8, 9])));

Related

What is a more optimized solution for this algorithm? I feel i can learn more from this question

First off am a beginner practicing my JavaScript. My solution to this problem will be posted. I think its worth mentioning this took almost two days of pondering to solve
The Problem:
I am required to write an algorithm that will return the mode(s) from the given input array. For example:
mode([4, 5, 6, 6, 6, 7, 7, 9, 10]) ➞ [6]
mode([4, 5, 5, 6, 7, 8, 8, 9, 9]) ➞ [5, 8, 9]
mode([1, 2, 2, 3, 6, 6, 7, 9]) ➞ [2, 6]
Solution:
function mode(nums) {
let array = [...nums]
array = array.sort((a, b) => a - b) //sorts the array from lowest value
// function to figure out the unique numbers and return as an array
function uniqueNums(array) {
let uniques = []
for (let i = 0; i < array.length; i++) {
if (!uniques.includes(array[i])) {
uniques.push(array[i])
}
}
return uniques
}
//function to return the mode of every unique number
function counter(array) {
let modes = []
for (let i = 0; i < array.length; i++) {
let count = 1, // keeps track of occurrence's of a number
track = 1 //variable enables the while loop keep checking
while (array[i] === array[i + track]) {
count++
track++
}
modes.push(count)
i += count - 1
}
return modes
}
//function to return the highest mode(s)
function highestMode(uniques, modes) {
let highest = [],
max = 0 //tracks our highest number in the array
//loops to find highest mode
for (let i = 0; i < modes.length; i++) {
if (max < modes[i]) {
max = modes[i]
}
}
//loops to push position of modes equal to the highest mode
for (let i = 0; i < modes.length; i++) {
if (max === modes[i]) {
highest.push(i)
}
}
//uses the position of highest modes to swap them with their
//actual values
let result = highest.map(a => a = uniques[a])
return result
}
return highestMode(uniqueNums(array), counter(array))
}
console.log(mode([4, 4, 4, 6, 8, 9, 10, 10]))
If you're looking at this as a learning exercise, here's another implementation of the same algorithm from CertainPerformance, but written quite differently.
const mode = (
ns,
counts = ns .reduce ((m, n) => m .set (n, (m .get (n) || 0) + 1), new Map ()),
max = Math .max (... counts .values())
) =>
[...counts] .flatMap (([n, c]) => c == max ? [n] : [])
console .log (mode ([4, 5, 6, 6, 6, 7, 7, 9, 10])) //=> [6]
console .log (mode ([4, 5, 5, 6, 7, 8, 8, 9, 9])) //=> [5, 8, 9]
console .log (mode ([1, 2, 2, 3, 6, 6, 7, 9])) //=> [2, 6]
If it's not clear, my counts matches to grouped and my max to maxCount.
The big difference from the answer by CertainPerformance is that this is written with pure expressions rather than statements. This is a style that I try to follow as much as I can do so practically.
It uses default parameters as a poor-man's substitute for let bindings available in other languages. It's not a perfect substitute and there is at least one potential problem with it, but it can be quite useful. Doing this let me define some helper variables that you can't assign in a function body without statements. There are alternatives, but I find this simplest when I can get away with it.
The reduce call is essentially the same as the other answer. So is the max definition.
But I take advantage of the fact that the default iterator of a Map is the list of entries, to turn the map into [[4, 1], [5, 1], [6, 3] ...] just by using the spread operator (...), without a need to call .entries().
Finally, I replace a call to filter and then to map with a single call to flatMap. This feels more elegant.
I'm not trying to suggest that this code is better than the one from CertainPerformance. It's quite similar in feel, although different in arrangement. But it is a different approach to the problem, and it might have something to offer because of that.
I'd count up the number of occurrences of each element into an Map. Then use Math.max to find the largest value(s) in the map, and then take the keys which are equal to that largest value:
const mode = arr => {
const grouped = new Map();
for (const item of arr) {
grouped.set(item, (grouped.get(item) || 0) + 1);
}
const maxCount = Math.max(...grouped.values());
return [...grouped.entries()]
.filter(([, count]) => count === maxCount)
.map(([key]) => key);
};
console.log(mode([4, 5, 6, 6, 6, 7, 7, 9, 10])) // ➞ [6]
console.log(mode([4, 5, 5, 6, 7, 8, 8, 9, 9])) // ➞ [5, 8, 9]
console.log(mode([1, 2, 2, 3, 6, 6, 7, 9])) // ➞ [2, 6]
A more simpler and optimized approach with single iteration
https://jsfiddle.net/dv7f9nxr/
function mode(items) {
var result = [];
var count = {};
var highest= 0;
items.map((item) => {
var itemCount = (count[item] || 0) + 1;
count[item] = itemCount;
if(itemCount > highest) {
highest = itemCount;
//reset
result = [item];
} else if (itemCount === highest){
result.push(item);
}
})
return result;
}
console.log(mode([2, 3, 9, 6, 9]))
console.log(mode([2, 3,2, 9, 6, 9]))
console.log(mode([2, 3,2, 9, 6, 9,2]))
console.log(mode([2, 3, 9, 6, 9,6,2]))

Return the sum of all even integers in array squared (javascript)

As the title says, I am trying to take an array of numbers, and then return the sum of all the even numbers in the array squared.
I can get my function to return the sum of all the even numbers in a given array, but cannot get it to square the sum of the even numbers.
Here is what I have so far:
let numStr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const squareEvenNumbers = (numStr) => {
let sum = 0;
for (let i = 0; i < numStr.length; i++) {
if (numStr[i] % 2 === 0) {
sum = Math.pow(sum + numStr[i], 2);
}
}
return sum
}
console.log(squareEvenNumbers(numStr));
You need to raise only the current item in the array to the power of 2, not the whole sum:
let numStr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const squareEvenNumbers = (numStr) => {
let sum = 0;
for (let i = 0; i < numStr.length; i++) {
if (numStr[i] % 2 === 0) {
sum += Math.pow(numStr[i], 2);
}
}
return sum
}
console.log(squareEvenNumbers(numStr));
Or, more concisely:
let numStr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const squareEvenNumbers = arr => arr
.filter(num => num % 2 === 0)
.reduce((a, num) => a + num ** 2, 0);
console.log(squareEvenNumbers(numStr));
Or, to only iterate over the array once:
let numStr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const squareEvenNumbers = arr => arr
.reduce((a, num) => a + (num % 2 === 0 && num ** 2), 0);
console.log(squareEvenNumbers(numStr));

Codewars javascript task - help to understand

I am taking an excercise on codewars:
Given a list of integers and a single sum value, return the first two
values (parse from the left please) in order of appearance that add up
to form the sum.
Example:
sum_pairs([10, 5, 2, 3, 7, 5], 10)
# ^-----------^ 5 + 5 = 10, indices: 1, 5
# ^--^ 3 + 7 = 10, indices: 3, 4 *
# * entire pair is earlier, and therefore is the correct answer
== [3, 7]
What do you think entire pair is earlier means? IMO if the sum of it's indexes is smallest. Now based on this assumption I made my solution and one test fails:
var sum_pairs=function(ints, s){
let i = 0;
let pair = [0, 0];
let ind = [100, 100]
let found = false;
function loop(i) {
if (i > ints.length) return pair;
ints.slice(i).forEach((curr, idx) => {
ints.slice(i+1).some((num, i) => {
let sum = curr + num;
let prevIndicies = ind[0] + ind[1];
if(sum === s && prevIndicies > idx + i) {
ind = [idx, i];
pair = [curr, num];
found = true;
return true;
}
})
})
i += 1;
loop(i)
}
loop(0)
if (found) {
return pair
}
return undefined;
}
console.log(sum_pairs([1,4,8,7,3,15], 8))
Test returns error that [1, 7] is expected.
I'm pretty sure what it means is they want the second element to be as leftward in the list as possible. For example, for
l5= [10, 5, 2, 3, 7, 5];
when trying to find a sum of 10, the desired output is
[3, 7]
[10, 5, 2, 3, 7, 5];
^ ^
instead of
[5, 5]
[10, 5, 2, 3, 7, 5];
^ ^
because the last element in [3, 7], the 7, came before the second 5.
This code seems to pass all test cases - iterate in a triangular fashion, starting at indicies [0, 1], [0, 2], [1, 2], [0, 3], [1, 3], [2, 3], ...:
const sum_pairs = function(ints, s){
const { length } = ints;
for (let i = 1; i < length; i++) {
for (let j = 0; j < i; j++) {
if (ints[i] + ints[j] === s) return [ints[j], ints[i]];
}
}
}
const sum_pairs=function(ints, s){
const { length } = ints;
for (let i = 1; i < length; i++) {
for (let j = 0; j < i; j++) {
if (ints[i] + ints[j] === s) return [ints[j], ints[i]];
}
}
}
l1= [1, 4, 8, 7, 3, 15];
l2= [1, -2, 3, 0, -6, 1];
l3= [20, -13, 40];
l4= [1, 2, 3, 4, 1, 0];
l5= [10, 5, 2, 3, 7, 5];
l6= [4, -2, 3, 3, 4];
l7= [0, 2, 0];
l8= [5, 9, 13, -3];
console.log(sum_pairs(l1, 8))
console.log(sum_pairs(l2, -6))
console.log(sum_pairs(l3, -7))
console.log(sum_pairs(l4, 2))
console.log(sum_pairs(l5, 10))
console.log(sum_pairs(l6, 8))
console.log(sum_pairs(l7, 0))
console.log(sum_pairs(l8, 10))
It means that you go from left to right and take the first matching pair, and since 7 is the first element that creats a pair (going from the left) 3 and 7 is the first pair.
I would solve it a bit easier:
function sum_pairs(arr, target) {
let old = [];
let result = [];
arr.some((el) => {
let found = old.find((oldEl) => oldEl + el === target);
if (found) return result = [found, el];
old.push(el);
})
return result;
}
sum_pairs([10, 5, 2, 3, 7, 5], 10);
Edit: an explaination. I loop over all elements in the array searching for a match i all the elements I have passed. If I find a match I remember it and break out of the loop by returning a "truthy" value. (That is just how .some() works.) Finally if I have not found a match I add the element to my list of old elements and go on to the next.
function sum_pair(arr,sum){
let result = [];
arr.forEach((i, j)=>{
if(i+arr[j+1]===sum){
console.log(i,arr[j+1], i+arr[j+1])
}
})
}
sum_pair([0, 3, 7, 0, 5, 5],10)

Iterate through array by sets of [unknown integer] [duplicate]

This question already has answers here:
Split array into chunks
(73 answers)
Closed 5 years ago.
Assuming I have an integer n which is greater than 0, and an array like this:
var array = [1, 2, 5, 6, 8, 9, 12, 13, 17...] //random values
How would I iterate through this array, going through and getting values n at a time (and putting it into a 2D array as well)?
If n were 3, for example, I would want a return value of
[[1, 2, 5], [6, 8, 9], [12, 13, 17]...]
And the code would be like this:
var array = [];
for (var i = 0; i < array.length; i += 3) {
var first = array[i];
var second = array[i+1];
var third = array[i+2];
array.push([
first, second, third
]);
}
Problem with this is that I have fixed values to get my objects by (the i, i+1, etc.)
If I have an unknown integer, then incrementing right up to n will not work.
How would I go about achieving this?
Use slice to take chunks and go through the array:
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
const partition = (n, arr) => {
const result = [];
let i = 0;
while(i < arr.length) {
result.push(arr.slice(i, i + n));
i = i + n;
}
return result;
};
console.log(partition(1, arr));
console.log(partition(2, arr));
console.log(partition(3, arr));
console.log(partition(4, arr));

Delete duplicate elements in an array [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 9 years ago.
Improve this question
For example, I have an array like this;
var arr = [1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 7, 8, 9, 10, 10]
If an element is repeated remove it completely
var arr = [1, 3, 4, 6, 8, 9]
Any tips, link or code example would be useful.
Thank you in advance!
Filter out items with more than 1 index
var arr = [1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 7, 8, 9, 10, 10];
arr = arr.filter(function (item, index, arr) {
return arr.indexOf(item) == arr.lastIndexOf(item);
});
arr
/* returned value: (Array)
1,3,4,6,8,9
*/
There is no need for a library, ES ed 3 support is sufficient. If the array is sorted per the OP, then:
function removeDups(a) {
var i = a.length && a.length - 1;
while (i) {
if (a[i] == a[--i]) {
a.splice(i, 1);
}
}
// Not required, but convenient
return a;
}
Edit
To remove all duplicates "completely" with an unsorted array (works with primitive or object values), consider:
// Removes duplicated elements comlpetely,
// e.g. [1,1,2,3,3] => [2]
// Requires ES5 Array.prototype.indexOf
function removeDupsUnsorted(a) {
var i = a.length;
var idx, v;
while (--i > -1) {
v = a[i];
idx = a.indexOf(v);
if (idx != i) {
do {
a.splice(idx, 1);
idx = a.indexOf(v);
i--;
} while (idx != -1)
++i;
}
}
return a;
}
Here is potentially an O(n) solution, assuming property lookup and insertion are O(1):
var arr = [1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 7, 8, 9, 10, 10];
var included = arr.reduce( function(a,b) {
a[b] = a[b]===undefined; return a}, {} );
arr.filter( function(c) { return included[c]; } )
// [1, 3, 4, 6, 8, 9]
It is actually faster with direct for loops rather than reduce and filter:
function removeDups5(a) {
var included = {}, i;
for( i=0 ; i<a.length ; ++i ) included[a[i]] = a[i] in included;
for( --i ; 0<=i ; --i ) if(included[a[i]]) a.splice(i,1);
return a;
}
Here is a jsperf comparing some of these answers to each other. This solution is currently in the lead, it seems, the longer the array is. (Anyone feel free to add your solution to it.)
You can use filter:
var arr = [1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 7, 8, 9, 10, 10];
arr = arr.filter(function (item, index, arr) {
return arr.indexOf(item) == arr.lastIndexOf(item);
});
console.log(arr); // [1, 3, 4, 6, 8, 9]
Fiddle Demo
I'm a little tired, but this should also do the trick (ECMA5) and original order should not matter.
Javascript
var arr = [1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 7, 8, 9, 10, 10];
arr = arr.filter(function (value, index, array) {
return (!this[value] && array.lastIndexOf(value) === index) || !(this[value] = true);
}, {});
console.log(JSON.stringify(arr));
Output
[1,3,4,6,8,9]
On jsFiddle
Assuming arr is sorted, here is an O(n) solution.
var arr = [1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 7, 8, 9, 10, 10]; //Make sure it's sorted!
var no_add;
var other = [];
other.push(arr[0]);
for (var i = 1; i < arr.length; i++)
{
if(no_add == arr[i])
continue;
if(other[other.length - 1] == arr[i])
{
no_add = other.pop();
continue;
}
else
other.push(arr[i]);
}
console.log(other); //[1, 3, 4, 6, 8, 9]

Categories