i wants to separate an array with two groups (odd and even) sequentially. but when i try this:
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
for (var i = 0; i < arr.length; i++) {
if (arr[i]%2 == 0) {
arr.push(arr.splice(i, 1)[0]);
}
}
console.log(arr);
console.log(arr);
// [1, 3, 5, 7, 9, 4, 8, 6, 2]
why 4,8,6,2 instead of 2,4,6,8?
Because you move every found even value to the end of the array:
0: 1 2 3 4 5 6 7 8 9
^-------------v
1: 1 3 4 5 6 7 8 9 2 3 is not checked, because of the incremented index after splicing
^-----------v
2: 1 3 5 6 7 8 9 2 4 5 is not checked
^---------v
3: 1 3 5 7 8 9 2 4 6 7 is not checked
^-------v
4: 1 3 5 7 9 2 4 6 8 9 is not checked
^-----v
5: 1 3 5 7 9 4 6 8 2
^---v
6: 1 3 5 7 9 4 8 2 6
^-v
7: 1 3 5 7 9 4 8 6 2
|
8: 1 3 5 7 9 4 8 6 2
But, you do not check the value after the found even value, like the value 3 in line zero, because it is never checked and stays at this place, as well as other actually uneven values. You could try the whole again with all even at the beginning of the array, like
var array = [2, 4, 6, 8, 1, 3, 5, 7, 9];
for (var i = 0; i < array.length; i++) {
if (array[i] % 2 === 0) {
array.push(array.splice(i, 1)[0]);
console.log(i + ': ' + array.join(' '));
}
}
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Solution
You could use a length for checking and reduce the length for every found even value. In this case, the index stays at the value, because at the index is now the next element for checking.
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9],
i = 0,
l = array.length;
while (i < l) {
if (array[i] % 2 === 0) {
array.push(array.splice(i, 1)[0]);
l--;
continue;
}
i++;
}
console.log(array);
Or just sort.
By moving odd values to top and then sort by value.
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9];
array.sort((a, b) => b % 2 - a % 2 || a - b);
console.log(array);
The way you do it is so complicated. You can simply achieve that with array.prototype.filter and array.prototype.concat:
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
arr = arr.filter(e => e%2).concat(arr.filter(e => e%2 === 0));
console.log(arr);
why 4,8,6,2 instead of 2,4,6,8?
Basically when half of the iterations are done, it is re-processing the pushed items.
You need to change the for-loop as
for (var i = 0; i < arr.length/2; i++) {
if (arr[i]%2 == 0) {
arr.push(arr.splice(i, 1)[0]);
}
}
Demo
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
for (var i = 0; i < arr.length / 2; i++) {
if (arr[i] % 2 == 0) {
arr.push(arr.splice(i, 1)[0]);
}
}
console.log(arr);
Edit
And if the order of items is not always sorted, then you apart from sorting it first, you can reduce the length variable.
var arr = [1, 2, 4, 3, 5, 6, 7, 8, 9];
var length = arr.length;
for (var i = 0; i < length; i++) {
console.log(i,arr[i]);
if (arr[i] % 2 == 0) {
arr.push(arr.splice(i, 1)[0]);
console.log("result ", arr)
length--;
i--;
}
}
console.log(arr)
why 4,8,6,2 instead of 2,4,6,8?
it is because you are modifying the same Array which you are looping through.
to understand better, lets loop through your code
after
1st Loop: array: [1, 2, 3, 4, 5, 6, 7, 8, 9];
2nd loop: array: [1, 3, 4, 5, 6, 7, 8, 9, 2];
3rd loop: array: [1, 3, 5, 6, 7, 8, 9, 2, 4];
4th loop: array: [1, 3, 5, 7, 8, 9, 2, 4, 6];
5th loop: array: [1, 3, 5, 7, 9, 2, 4, 6, 8];
6th loop: array: [1, 3, 5, 7, 9, 4, 6, 8, 2];
7th loop: array: [1, 3, 5, 7, 9, 4, 8, 2, 6];
8th loop: array: [1, 3, 5, 7, 9, 4, 8, 6, 2];
9th loop: array: [1, 3, 5, 7, 9, 4, 8, 6, 2];
to separate out odd/even in an array,
we will have to filter out odd and even separately and push evenArray in the end of oddArray(filtered Array)
var input = [1, 2, 3, 4, 5, 6, 7, 8, 9];
input = input.sort((a, b)=> a-b); //to sort array if not sorted already
var evenArr = [];
input = input.filter(item => {
if (item % 2 != 0)
return true
else {
evenArr.push(item);
return false;
}
})
Array.prototype.push.apply(input, evenArr);
console.log(input);
I believe this can be covered by lodash _.partition:
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var [odds, evens] = _.partition(arr, function(n) {
return n % 2;
});
console.log(_.concat(odds, evens));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Or even shorter:
_.groupBy(arr, function(n) {return (n % 2) ? 'odd' : 'even';})
Related
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]
var valid1=[4, 5, 3, 9, 6, 7, 7, 9, 0, 8, 0, 1, 6, 8, 0, 8]
function validateCred(array) {
let doubleArray =0
for(i=array.length-2; i >= 0; i-=2) {
doubleArray= array[i]*2
}
console.log(doubleArray);
}
validateCred(valid1) //prints 8 I want it to print entire loop
Im trying to code luhn Algorithm and this is the first step of doubling every second number from the back, i want my result to equal doubleArray however when i try print it only 8 prints
you have only 8 prints because you have step i-2. Also, see comments in code about reversing an array
const valid1 = [4, 5, 3, 9, 6, 7, 7, 9, 0, 8, 0, 1, 6, 8, 0, 8];
function validateCred(array) {
let doubleArray = [];
// we should move through all iterations that is why step i-=1
for(let i = array.length-1; i >= 0; i -= 1) {
// moving from the end of the array we will get reversed copy if using method push()
// that is why changed to unshift()
doubleArray.unshift((array.length - 1 - i) % 2 == 0 ? array[i] * 2 : array[i]);
// array.length - 1 - i - using because we need to move from right in case length not odd
}
console.log(doubleArray);
}
// ES6+ syntax version version
function esValidateCred1(array) {
const doubleArray = array.reverse().map((i, ind) => ind % 2 === 0 ? i*2 : i).reverse();
console.log(doubleArray);;
}
validateCred(valid1);
esValidateCred1(valid1);
You can refer the code below to get the desired output i.e. the an array with doubled value starting from back.
var valid1=[4, 5, 3, 9, 6, 7, 7, 9, 0, 8, 0, 1, 6, 8, 0, 8]
function validateCred(array) {
let doubleArray = [];
for(i=array.length-2; i >= 0; i-=2) {
doubleArray.push(array[i] * 2)
}
return(doubleArray);
}
console.log(validateCred(valid1))
the easiest way is to use .map() method for array
var valid1=[4, 5, 3, 9, 6, 7, 7, 9, 0, 8, 0, 1, 6, 8, 0, 8]
function validateCred(array) {
return array.map(item => item*2);
}
console.log( validateCred(valid1) ) //prints array doubled elements
Considering, I have an array like this [..., n-2, n-1, n, n+1, n+2, ...]. I would like to sort it in this way [n, n+1, n-1, n+2, n-2,...] with n equals to the middle of my array.
For example:
Input:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Output:
[5, 6, 4, 7, 3, 8, 2, 9, 1, 0]
let arrayNotSorted = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
let positionMiddleArray = Math.trunc(arrayNotSorted.length / 2);
let arraySorted = [arrayNotSorted[positionMiddleArray]];
for(let i=1; i <= positionMiddleArray; i++){
if(arrayNotSorted[positionMiddleArray + i] !== undefined){
arraySorted.push(arrayNotSorted[positionMiddleArray + i]);
}
if(arrayNotSorted[positionMiddleArray - i] !== undefined){
arraySorted.push(arrayNotSorted[positionMiddleArray - i]);
}
}
console.log('Not_Sorted', arrayNotSorted);
console.log('Sorted', arraySorted);
What I have done works properly, but I would like to know if there is a better way or a more efficient way to do so ?
You could take a pivot value 5 and sort by the absolute delta of the value and the pivot values an sort descending for same deltas.
var array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
pivot = 5;
array.sort((a, b) => Math.abs(a - pivot) - Math.abs(b - pivot) || b - a);
console.log(...array); // 5 6 4 7 3 8 2 9 1 0
You can do that in following steps:
Create an empty array for result.
Start the loop. Initialize i to the half of the length.
Loop backwards means decrease i by 1 each loop.
push() the element at current index to the result array first and the other corresponding value to the array.
function sortFromMid(arr){
let res = [];
for(let i = Math.ceil(arr.length/2);i>=0;i--){
res.push(arr[i]);
res.push(arr[arr.length - i + 1])
}
return res.filter(x => x !== undefined);
}
console.log(sortFromMid([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))
[5, 6, 4, 7, 3, 8, 2, 9, 1, 0]
i have 2 rows that i need to check in java script if they are symmetrical
row 1 [2, 7, 9, 9, 7, 2] row 2 [5 7 3 3 7 5] how would you do it ?
var r = [[5, 7, 3, 3, 7, 5], [2, 7, 9, 9, 7, 2]];
function isSymmetric(r) {
// convert to object
var rel = {}
for (var i = 0; i < r.length; i++) {
if (!(r[i][0] in rel)) rel[r[i][0]] = {};
rel[r[i][0]][r[i][1]] = true;
}
// Test to see if opposite relation is in object
for (var a in rel) {
for (var b in rel[a]) {
if (!rel[b] || !rel[b][a]) return false;
}
}
return true;
}
console.log(isSymmetric(r));
You could do something like this:
let isSymmetric = arr => {
for(var i=0; i < arr.length; i++) {
if(arr[i] !== arr[arr.length - (i+1)])
return false
}
return true
}
console.log(isSymmetric([5, 7, 3, 3, 7, 5]))
console.log(isSymmetric([1, 7, 9, 9, 7, 2]))
The idea is to loop through the array and for each index compare with its "sibling" from the right side. If one is not the same them return false.
You can start from 0th index and compare the value with its symmetric pair (length - 1 - i), and if they are not same then return false. You should stop at the middle length / 2:
let values = [
[5, 7, 3, 3, 7, 5],
[2, 7, 9, 1, 9, 7, 2],
[5, 7, 3, 3, 7, 1]
];
function isSymmetric(arr) {
for (let i = 0; i < arr.length / 2; i++) {
if (arr[i] !== arr[arr.length - 1 - i]) {
return false;
}
}
return true;
}
values.forEach(v =>
console.log(isSymmetric(v))
);
Use lodash.
var row = [2, 7, 9, 9, 7, 2];
var halves = _.chunk(row, _.ceil(row.length / 2));
var result = _.isEqual(halves[0], _.reverse(halves[1]));
I want a function that returns the sub array which takes a position & the no. of elements I want. I think there may be some algorithm to find the pivot point or something & from that I can get the sub array, but I totally forgot it.
Example: a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
I want 6 elements
if position = 0, then I want [1, 2, 3, 4, 5, 6]
if position = 1, then [1, 2, 3, 4, 5, 6]
if position = 2, then [1, 2, 3, 4, 5, 6]
if position = 3, then [1, 2, 3, 4, 5, 6]
if position = 4, then [2, 3, 4, 5, 6, 7]
if position = 5, then [3, 4, 5, 6, 7, 8]
if position = 6, then [4, 5, 6, 7, 8, 9]
if position = 7, then [5, 6, 7, 8, 9, 10]
if position = 8, then [5, 6, 7, 8, 9, 10]
if position = 9, then [5, 6, 7, 8, 9, 10]
simply get the middle of N elements based on the position I pass.
I can write up my own loop which will contain multiple if-else conditions to get it done. But I feel there may be some easy way to do it.
I didnt include my incomplete code snippet because I strongly feel there must be some algorithm to do this.
What you want is : Array.prototype.slice(...)
It's neatly documented here : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice
var n = 6;
var start = Math.max(0, Math.min(Math.floor(position-n/2), a.length-n));
return a.slice(start, start+n);
Simple way:
var a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
function getSubArray(idx, _length, _array) {
return _array.slice(idx, idx + _length);
}
var subArray = getSubArray(3, 6, a);
You could use an offset for the postion and get the the start value first for slicing.
var a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
n = 6,
i,
start;
for (i = 1; i < 12; i++) {
start = Math.max(Math.min(i - n / 2, a.length - n), 0);
console.log(i, ': ', a.slice(start, start + n).join());
}
Your only need is to check if you are not gonna check a pos that doesn't exist. Like :
var a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var n = 6; // Number of result you want
var x = 8; // Pos you want
// If you gonna exceed your length, we got only the n last element
if((x+(n/2)) > a.length) {
console.log(a.slice(a.length-n));
// Otherwise, if under 0, we got the n first
} else
if((x-(n/2)) < 0) { console.log(a.slice(0,n) );
// Default case
} else {
console.log(a.slice((x-(n/2)),(x+(n/2))));
}
This is not the smartest way, but he can give you some hint. I used the slice as other mentionned to avoid a lot of if, but you should do GENERIC test.
Something like this :
a = [1,2,3,4,5,6,7,8,9,10];
n = 6;
function split(position) {
var start = Math.min(Math.max(position - Math.floor(n/2), 0), a.length - n);
var stop = Math.min(start+n, a.length);
return a.slice(start, stop);
}
No need for the Math object at all. You may simply do as follows;
function getArr(a,n,d){
n = n - 4 < 0 ? 0
: a.length - d > n - 4 ? n - 3
: a.length - d;
return a.slice(n,n + d);
}
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
diff = 6;
for (var i = 0; i < 10; i ++) console.log(JSON.stringify(getArr(arr,i,diff)));
no need of if-else you can use arr[position] to arr[8]. have you got
function getArr(arr,position,requiredNumbers){
return arr.slice(position, position+requiredNumbers);
}