array return index from another array - javascript

suppose we have this two array. in some condition, I want to return the index of a second array.
let a = [1, 2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 , 12]
let b = [0, 1, 2, 3 , 4 , 5, 6 , 7 , 8, 9, 10, 11]
if (a[2]) ? return b[2] : return null
why I need this? because I have a month number of the year that starts from 0 to 11. but I need to turn this 1 12 for storing in my database.
sry about the title of this question if someone has a better title I would be glad about changing it.

You could calculate the value by adding 11 and get the remainder value with 12.
function getZeroBasedMonth(n) {
return (n + 11) % 12;
}
console.log(getZeroBasedMonth(1));
console.log(getZeroBasedMonth(12));
For the getting the opposite, just add one.
function getMonth(n) {
return n + 1;
}
console.log(getMonth(0));
console.log(getMonth(11));

Why make this harder than it needs to be? Just add 1 to the value you get from your initial array. Here is, per your comment, 10 years worth of values for the months with a +1 value.
let years = 10;
let months = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
let allYears = [];
for(let i = 0; i < years; i++){
let year = [];
for(let x = 0; x < months.length; x++){
year[x] = months[x] + 1;
}
allYears.push(year);
}
console.log(allYears);

Related

Loops with multiple conditions

I was aiming to make this problem shorter with less variables and to only mutate the original array1, but after I noticed that addedOddNumbers (value of 9) was not adding to the odd numbers of array1 while using a for loop I decided to break it down as much as possible.
When I started to break it down as shown below I then tried adding addedEvenNumbers to over10 with the for loop. This worked and gave me 23, 21, but the same if statement above with addedOddNumbers to under10 prints me 2, 4, 9.
Meanwhile addedEvenNumbers prints out 23 and 21 which was what I was looking for originally with the addedOddNumbers too. Can someone please explain why that although they are the same exact if statement/expression that one is iterating through and adding while the other is not?
Note: I'd like to see this solved as close as possible to to what I have written out. I have seen other solutions, but I can't read the other solutions to be able to answer my own question.
function addingAllTheWeirdStuff(array1, array2) {
let addedOddNumbers = 0 // 9
let addedEvenNumbers = 0 // 6
let under10 = [] // 1, 3, 5
let over10 = [] // 17, 15
let result = [] // should be 10, 12, 14, 23, 21 --- current result is 2, 4, 9, 23, 21
for (let i = 0; i < array2.length; i++) {
if (array2[i] % 2 === 1) {
addedOddNumbers += array2[i]
}
if (array2[i] % 2 === 0) {
addedEvenNumbers += array2[i]
}
if (array1[i] < 10) {
under10.push(array1[i] + addedOddNumbers)
}
if (array1[i] > 10) {
over10.push(array1[i] + addedEvenNumbers)
}
}
console.log(addedOddNumbers)
console.log(addedEvenNumbers)
console.log(under10) // why????
console.log(over10) // this works fine but why not under10?
result.push(...under10, ...over10)
console.log(result)
}
console.log(addingAllTheWeirdStuff([1, 3, 5, 17, 15], [1, 2, 3, 4, 5]));
// expected log [10, 12, 14, 23, 21]
It's not the final result of addedOddNumbers and addedEvenNumbers that is added to the values of over10 and under10, but their current value inside the loop. The over10 values are correct because they are at the end of the array and by then all the even numbers are already added to addedEvenNumbers.

Splitting an array into equal chunks and then allot remaining

I have a array where I need to divide equally into person number of chunks.
if there are 100 items in array for 10 persons, 10 chunks to be created with each 10 items
if there are 100 items in array for 9 persons, 9 chunks to be created and each would get 9 items and the extra should be given to first person, second person and so on. which means Person 1 = 10; Person 2, 3, 4 ... would have 9 items
if there are 100 items in array for 11 persons, 11 chunks are to be created with each would get 10 and the extra should be given to first person. which means
Person 1 is 10
Person 2 is 9
Person 3 is 9
Person 4 is 9
Person 5 is 9
Person 6 is 9
Person 7 is 9
Person 8 is 9
Person 9 is 9
Person 10 is 9
Person 11 is 9
I have tried with
Object.defineProperty(Array.prototype, 'chunk', {
value: function(chunkSize) {
var array = this;
return [].concat.apply([],
array.map(function(elem, i) {
return i % chunkSize ? [] : [array.slice(i, i + chunkSize)];
})
);
}
});
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ..., 150, 151].chunk(Math.floor(151 / 31))
but that would gives me an incorrect allocation.
Use the remainder of the division to get the number of slices that need an extra element. Then use the index in the new (chunked) array to determine whether it needs that extra element (i.e. when that index is less than the remainder).
NB: I would not alter the Array prototype. Just make this a plain function.
Implementation:
function partition(arr, length) {
let rest = arr.length % length;
let size = Math.floor(arr.length / length);
let j = 0;
return Array.from({length}, (_, i) => arr.slice(j, j += size + (i < rest)));
}
let data = Array.from({length: 151}, (_,i) => i+1);
let result = partition(data, 31);
console.log(result);
You can use generators to split an array in chunk:
function* chunks(arr, n) {
for (let i = 0; i < arr.length; i += n) {
yield arr.slice(i, i + n);
}
}
let a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ..., 150, 151];
console.log([...chunks(a, Math.floor(151 / 31))]);
Then you can adapt this code to move the last element in first place (if you want first person to be the most empty).
As a side note, you can replace this:
let a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ..., 150, 151];
with this:
let a = [...Array(151).keys()];

Group numbers from array that are right after each other

I have an array with some numbers like the following:
[1, 2, 3, 4, 6, 7, 8, 10, 15, 16, 17]
I'd like to show all numbers that are direct after each other (n+1) in one line and if there is a gap, this should be separated. This will either be done in javascript/jquery.
The user would see it like this:
1 - 4, 6 - 8, 10, 15 - 17
I'm guessing the only solution to this would be to loop through the array and see if the next number is n+1 and if it is, lump it together, else start on a new series?
I think I know how I would do it that way but interested to know if there is some other way to do it either in javascript/jquery?
You can loop once while keeping track of the current starting number.
let arr = [1, 2, 3, 4, 6, 7, 8, 10, 15, 16, 17];
let start = arr[0],
res = [];
for (let i = 1; i < arr.length; i++) {
if (arr[i + 1] - arr[i] != 1 || i == arr.length - 1) {
res.push(start + " - " + arr[i]);
start = arr[i + 1];
}
}
console.log(res);

Why is splicing an array in JavaScript removing the last few elements?

I'm currently working on an array function that converts subarrays of consecutive numbers into strings denoting that range of numbers — for example, this array...
[1, 2, 3, 6, 8, 10, 11, 12, 15, 18]
...would become this array:
["1-3", 6, 8, "10-12", 15, 18]
I've been able to develop a function that mostly works, but I've encountered a weird error where all the elements past the final range of numbers spliced into the array are completely deleted. For example, the test array above actually becomes this:
["1-3", 6, 8, "10-12"]
This is the code I've written so far. It's not super pretty yet, but as I mentioned above, it gets the job done right up until the very end:
let testArray = [1, 2, 3, 6, 8, 10, 11, 12, 15, 18];
for (i = 0; i < testArray.length; i++) {
let consecutives = [];
consecutives.push(testArray[i]);
let j = i + 1;
while (j < testArray.length) {
if (testArray[j] == (testArray[j - 1] + 1)) {
consecutives.push(testArray[j]);
j++;
} else {
break;
}
}
if (consecutives.length > 2) {
let range = String(testArray[i]) + "-" + String(testArray[j - 1]);
console.log(testArray);
console.log(testArray[i]);
console.log(testArray[j]);
testArray.splice(i, j, range);
}
}
console.log(testArray);
These are the console logs output by that code:
Array(10) [ 1, 2, 3, 6, 8, 10, 11, 12, 15, 18 ]
1
6
Array(8) [ "1-3", 6, 8, 10, 11, 12, 15, 18 ]
10
15
Array(4) [ "1-3", 6, 8, "10-12" ]
I initially figured this was caused by a mix-up with array indexes, but playing around with the index-1s hasn't fixed the problem yet. Has anyone else ever had a similar issue with JavaScript's splicing, and if so, how were you able to get it working?
The problem lies in one line of code:
testArray.splice(i, j, range);
According to the MDN, the second argument specifies how many elements in the array to delete.
deleteCount
An integer indicating the number of elements in the array to remove from start.
However, the code defines this argument as the index of the last array to remove from:
let j = i + 1;
The solution is to get the difference between i and j before passing it to splice:
testArray.splice(i, j - i, range);
When you do:
testArray.splice(i, j, range);
You are forgetting that j is the right limit index of the array that you want to erase, so you need to subtract i that is the left limit:
testArray.splice(i, j - i, range);
let testArray = [1, 2, 3, 6, 8, 10, 11, 12, 15, 18];
for (i = 0; i < testArray.length; i++) {
let consecutives = [];
consecutives.push(testArray[i]);
let j = i + 1;
while (j < testArray.length) {
if (testArray[j] == (testArray[j - 1] + 1)) {
consecutives.push(testArray[j]);
j++;
} else {
break;
}
}
if (consecutives.length > 2) { // doesn´t it should be > 1 ??
let range = String(testArray[i]) + "-" + String(testArray[j - 1]);
console.log(testArray);
console.log(testArray[i]);
console.log(testArray[j]);
testArray.splice(i, j - i, range);
}
}
console.log(testArray);

Find the longest sub array of consecutive numbers with a while loop

I want to write a function with a while-statement that determines the length of the largest consecutive subarray in an array of positive integers. (There is at least one consecutive array.) For instance:
Input: [6, 7, 8, 6, 12, 1, 2, 3, 4] --> [1,2,3,4]
Output: 4
Input: [5, 6, 1, 8, 9, 7] --> [1,8,9]
Output: 3
Normally I would try to use for-loops and the array.push method later on, however, to get more practice I wanted to use a while-loop and another 'array-lengthening' method, not sure how it's called, see below.
My try:
function longestSub (input) {
let i=0;
let idx=0;
let counterArr=[1]; //init. to 1 because input [4,5,3] equals sub-length 2
while(i<input.length) {
if (input[i]+1 > input[i]) {
counterArr[0+idx] += 1
}
else {
i=input.indexOf(input[i]); //should start loop at this i-value again
idx +=1;
counterArr[0+idx] = 1; //should init new array index
}
i++
}
return Math.max(...counterArr)
}
My idea was that the else-statement would reset the if-statement when it fails and start again from the position it failed at with updated variables. It would also initialize another array index with value 1 that gets subsequently updated afterwards with the if-statement.
Finally I have a counterArr like [1,2,3] where 3 stands for the largest consecutive subarray. Thanks everyone reading this or helping a beginner like me to get a deeper understanding of Javascript.
Here is a simple solution using while loop:
let arr =[6, 7, 8, 6, 12, 1, 2, 3, 4]
let endIndx = 0, maxLength = 0, indx = 1,tempMax = 0;
while (indx < arr.length) {
if (arr[indx] > arr[indx - 1])
tempMax++;
else {
if (maxLength <= tempMax) {
maxLength = tempMax+1
endIndx = indx
tempMax=0;
}
}
++indx
}
if (maxLength < tempMax) {
maxLength = tempMax
endIndx = indx
}
console.log("Sub array of consecutive numbers: ", arr.slice(endIndx-maxLength,endIndx))
console.log("Output :",maxLength)
You could take an approach which just counts the length and checks with the max found length if the continuous items.
function longestSub(input) {
let i = 1, // omit first element and use later element before this index
max = 0,
tempLength = 1; // initialize with one
if (!input.length) return 0;
while (i < input.length) {
if (input[i - 1] < input[i]) {
tempLength++;
} else {
if (max < tempLength) max = tempLength;
tempLength = 1;
}
i++;
}
if (max < tempLength) max = tempLength;
return max;
}
console.log(longestSub([])); // 0
console.log(longestSub([6, 7, 8, 6, 12])); // 3
console.log(longestSub([5, 6, 1, 2, 8, 9, 7])); // 4
console.log(longestSub([6, 7, 8, 6, 12, 1, 2, 3, 4, 5])); // 5
Unless this really is a learning exercise, I'd rather focus on the approach than on the implementation.
Create a function that slices an array of numbers into arrays of consecutive numbers:
The first two conditions deal with the simplest cases:
If input is empty, output is empty [] -> []
If input is exactly one element, the output is known already [42] -> [[42]]
Then comes the "meat" of it. The output is an array of array. Let's start by creating the first sub array with the first element of the initial array. Let's use [6, 7, 8, 6, 12, 1 ,2 ,3, 4, 5] as the input.
Start with [[6]] then iterate over [7, 8, 6, 12, 1 ,2 ,3, 4, 5]. Here are the result at each iteration:
7 > 6 true -> [[6,7]]
8 > 7 true -> [[6,7,8]]
6 > 8 false -> [[6],[6,7,8]]
12 > 6 true -> [[6,12],[6,7,8]]
1 > 12 false -> [[1],[6,12],[6,7,8]]
2 > 1 true -> [[1,2],[6,12],[6,7,8]]
3 > 2 true -> [[1,2,3],[6,12],[6,7,8]]
4 > 3 true -> [[1,2,3,4],[6,12],[6,7,8]]
5 > 4 true -> [[1,2,3,4,5],[6,12],[6,7,8]]
const slices =
xs =>
xs.length === 0 ? []
: xs.length === 1 ? [[xs[0]]]
: xs.slice(1).reduce
( ([h, ...t], x) =>
x >= h[h.length - 1]
? [h.concat(x), ...t]
: [[x], h, ...t]
, [[xs[0]]]
);
slices([6, 7, 8, 6, 12, 1 ,2 ,3, 4, 5]);
//=> [ [1, 2, 3, 4, 5]
//=> , [6, 12]
//=> , [6, 7, 8]
//=> ]
Then you create a function that takes an array of slices and return the biggest one:
const max_slices =
xs =>
xs.reduce
( (a, b) =>
a.length > b.length
? a
: b
);
max_slices(slices([6, 7, 8, 6, 12, 1 ,2 ,3, 4, 5]));
//=> [1, 2, 3, 4, 5]

Categories