Check if Javascript array values are in ascending order - javascript

Say I have an array of integers in Javascript, that I would like to check if all of its values are in ascending order. What i want is to save the array key in another array in case the algorithm finds a value that is lower (or equal) not only comparing the immediate previous one, but also comparing any value that is before it.
What I did was this:
arr = [], nonvalid = [];
for (var j = 1; j < arr.length; j++){
if ( arr[j+1] <= arr[j] ){
nonvalid.push(j);
}
}
Obviously the above algorightm checks only for values that are lower comparing the one before it.
An array might contain values like these:
arr = 1, 2, 3, 10, 5, 11, 12, 2, 4, 25
The non valid values are the bold ones. If I run the above loop, it won't "catch" the second last one (4), because it's higher than its closest left brother, but not that high than its all left brothers.
EDIT:
Tried the following solutions and none return all the nonvalid values for this array except mine . :(
They returned the last two values correctedly, but not the second one.
I don't understand why though.
[24398, 24397, 25004, 25177, 26302, 28036, 29312, 29635, 29829, 30476, 32595, 33732, 34995, 36047, 36363, 37310, 38022, 38882, 40746, 41212, 42846, 43588, 44029, 44595, 44846, 45727, 46041, 47293, 48002, 48930, 49858, 51184, 51560, 53895, 54247, 54614, 55713, 56813, 57282, 57480, 57875, 58073, 58403, 60321, 61469, 62051, 62310, 62634, 63217, 64505, 65413, 65677, 65940, 66203, 66572, 67957, 68796, 68964, 69098, 69233, 69435, 69759, 71496, 72577, 72823, 73007, 73252, 73743, 73866, 76405, 77037, 77416, 77669, 79691, 80885, 81339, 81794, 82067, 82431, 83244, 84861, 86836, 88632, 89877, 90296, 91049, 91885, 92351, 92614, 93141, 93733, 93930, 94531, 95206, 95882, 96895, 97732, 97973, 99261, 99422, 99583, 100332, 100599, 101666, 102066, 102600, 103504, 104432, 105174, 107216, 109085, 110181, 110679, 111177, 111988, 112553, 113005, 113457, 600, 600]

One other very nice functional way of doing this could be;
var isAscending = a => a.slice(1)
.map((e,i) => e > a[i])
.every(x => x);
console.log(isAscending([1,2,3,4]));
console.log(isAscending([1,2,5,4]));
Nice code but there are redundancies in it. We can further simplify by consolidating .map() and .every() into one.
var isAscending = a => a.slice(1)
.every((e,i) => e > a[i]);
console.log(isAscending([1,2,3,4]));
console.log(isAscending([1,2,5,4]));

Keep track of the largest value you have seen (see the fiddle):
function find_invalid_numbers(arr) {
var nonvalid, i, max;
nonvalid = [];
if (arr.length !== 0) {
max = arr[0];
for (i = 1; i < arr.length; ++i) {
if (arr[i] < max) {
nonvalid.push(arr[i]);
} else {
max = arr[i];
}
}
}
return nonvalid;
}

When you find an element out of order, look at the next elements until they are no longer out of order relative to the element before the out of order one.
Add the out of order elements to the second array and continue from the new in order element.
var outs= [], L= A.length, i= 0, prev;
while(i<L){
prev= A[i];
while(A[++i]<prev) outs.push(i);
}
alert(outs)

Why not compare with the last known good number?
var arr = [1, 2, 3, 10, 5, 11, 12, 2, 4, 25],
nonvalid = [],
lastGoodValue = 0;
for (var j = 1; j < arr.length; j++) {
if (j && arr[j] <= lastGoodValue) {
//if not the first number and is less than the last good value
nonvalid.push(arr[j]);
} else {
//if first number or a good value
lastGoodValue = arr[j];
}
}
console.log(arr, nonvalid)

DEMO
var arr = [24398, 24397, 25004, 25177, 26302, 28036, 29312, 29635, 29829, 30476, 32595, 33732, 34995, 36047, 36363, 37310, 38022, 38882, 40746, 41212, 42846, 43588, 44029, 44595, 44846, 45727, 46041, 47293, 48002, 48930, 49858, 51184, 51560, 53895, 54247, 54614, 55713, 56813, 57282, 57480, 57875, 58073, 58403, 60321, 61469, 62051, 62310, 62634, 63217, 64505, 65413, 65677, 65940, 66203, 66572, 67957, 68796, 68964, 69098, 69233, 69435, 69759, 71496, 72577, 72823, 73007, 73252, 73743, 73866, 76405, 77037, 77416, 77669, 79691, 80885, 81339, 81794, 82067, 82431, 83244, 84861, 86836, 88632, 89877, 90296, 91049, 91885, 92351, 92614, 93141, 93733, 93930, 94531, 95206, 95882, 96895, 97732, 97973, 99261, 99422, 99583, 100332, 100599, 101666, 102066, 102600, 103504, 104432, 105174, 107216, 109085, 110181, 110679, 111177, 111988, 112553, 113005, 113457, 600, 600],
nonvalid = [],
max = arr[0];
for(var j=0; j<arr.length; j++){
var test= arr[j+1]<=max ? nonvalid.push(arr[j+1]) : max=arr[j];
}
alert(nonvalid); // 24397, 600, 600

a simple functional way to do it inline without loops or variables:
arr.filter(function(a,b,c){
return Math.max.apply(Math, c.slice(0,b)) > a ;
});

You can use map with this example:
const ascendingArray = [1,2,3,4,5,6,7];
const descendingArray = [1,2,3,7,5,6,4]
const isAscending = array => array.map((a, i) => a > array[i + 1]).indexOf(true) === -1
console.log(isAscending(descendingArray)); // should be false
console.log(isAscending(ascendingArray)); // should be true
Or, you can use filter with this example:
const ascendingArray = [1,2,3,4,5,6,7];
const descendingArray = [1,2,3,7,5,6,4]
const isAscending = array => array.filter((a, i) => a > array[i + 1]).length === 0;
console.log(isAscending(ascendingArray)); // should be true
console.log(isAscending(descendingArray)); // should be false

Copy the array first, remove any element that is not in order with array.splice(index, 1), and continue. That way, any element must by greater than the one right before it, but the one right before it will always be the max.

Answering my own question after taking your advices I tried the following algorightm. It seems to do its job but its a bit overkill.
for (var i = 0; i < arr.length; i++){
for (var j = 1; j < arr.length; j++){
if ( arr[j] > 0 && arr[i] > 0 && j != i ){
if ( arr[j] <= arr[i] && j > i ){
if ( jQuery.inArray(j, nonvalid) == - 1) nonvalid.push(j);
}
}
} }

Related

How to compare different indexes in array using Javascript array methods

I'm trying to solve the problem below but I'm stuck in knowing how to compare one index with another that's not consequently for example:
const arr = ["Juan", "Maria", "Maria", "Juan"]
In this case, comparing index 1 and 2 would be simple, but how can I pick index 0 and then compare it with each one of the others until it get to index 3 to be matched?.
Exercise
Input: USA, AUSTRALIA, AUSTRALIA, INDIA, FRANCE, USA
Print out the name of the Country and word "Bingo" if the element (Country name) is repeated and located one after another
Print out the name of the Country and word "Hooray" if the element (Country name) is repeated and located not consequently
Note: Use any Array method
Expected result: "Bingo Australia" "Hooray USA"
This is what I've tried.
Note that if I run it that way it would work but only because I'm accessing countries[index + 5].
How can I make the index to dynamically increases itself when the iteration finishes?
const countries = ['USA', 'Australia', 'Australia', 'France', 'India', 'USA'];
countries.forEach((value, index) => {
if (countries[index] === countries[index + 1]) {
console.log(`Bingo ${value}`);
} else if (countries[index] === countries[index + 5]) {
console.log(`Hooray ${value}`);
}
});
You can try something like this, it is not most efficient but it will solve your problem:
const countries = ['USA', 'Australia', 'Australia', 'France', 'India', 'USA'];
countries.forEach((value, index, arr) => {
arr.forEach((val, idx) => {
if (val === value && index < idx) {
if (idx === index + 1) console.log(`Bingo ${value}`);
else console.log(`Hooray ${value}`);
}
});
});
Solution with a lot of 'if' (just reduce iterations (loop count)
Wrote with purpose with for loop, in reality, it is same as a nested loop.
const c_arr = [1, 4, 5, 5, 6, 7, 4, 1];
let j = 0;
let full_count = 0; //count loops
for (let i = 0; i < c_arr.length; ++i) {
if (j === 0 & c_arr[i] === c_arr[i + 1]) { // condition j ==0 so it will go inside only in first loop
console.log('Bingo', c_arr[i])
}
// console.log("Test", c_arr[j]);
if (i + 2 < c_arr.length & c_arr[j] === c_arr[i + 2]) { // i+2 cond, to avoid to access elem. outside array
console.log('Hooray', c_arr[i + 2]);
c_arr[j] = null;
}
// All to reduce loop count
if (j > 0 & c_arr[j] === null) { // allneigbourgh elements are checked
i = j;
++j;
}
if (j > 0 & i === c_arr.length - 3) { // avoid empty loop, condition for Hooray is i+2
i = j;
++j;
}
if (i === c_arr.length - 1) { // on first loop increase j
i = j;
++j;
}
// to stop loop when J reaches arr :-2 element
if (j === c_arr.length - 2) {
i = c_arr.length;
}
++full_count;
}
console.log(full_count, " :loops count");

How to get all possible combination of jagged arrays? [duplicate]

This question already has answers here:
Cartesian product of multiple arrays in JavaScript
(35 answers)
Closed 1 year ago.
I'm having trouble coming up with code to generate combinations from n number of arrays with m number of elements in them, in JavaScript. I've seen similar questions about this for other languages, but the answers incorporate syntactic or library magic that I'm unsure how to translate.
Consider this data:
[[0,1], [0,1,2,3], [0,1,2]]
3 arrays, with a different number of elements in them. What I want to do is get all combinations by combining an item from each array.
For example:
0,0,0 // item 0 from array 0, item 0 from array 1, item 0 from array 2
0,0,1
0,0,2
0,1,0
0,1,1
0,1,2
0,2,0
0,2,1
0,2,2
And so on.
If the number of arrays were fixed, it would be easy to make a hard coded implementation. But the number of arrays may vary:
[[0,1], [0,1]]
[[0,1,3,4], [0,1], [0], [0,1]]
Any help would be much appreciated.
Here is a quite simple and short one using a recursive helper function:
function cartesian(...args) {
var r = [], max = args.length-1;
function helper(arr, i) {
for (var j=0, l=args[i].length; j<l; j++) {
var a = arr.slice(0); // clone arr
a.push(args[i][j]);
if (i==max)
r.push(a);
else
helper(a, i+1);
}
}
helper([], 0);
return r;
}
Usage:
cartesian([0,1], [0,1,2,3], [0,1,2]);
To make the function take an array of arrays, just change the signature to function cartesian(args) instead of using rest parameter syntax.
I suggest a simple recursive generator function:
// JS
function* cartesianIterator(head, ...tail) {
const remainder = tail.length ? cartesianIterator(...tail) : [[]];
for (let r of remainder) for (let h of head) yield [h, ...r];
}
// get values:
const cartesian = items => [...cartesianIterator(items)];
console.log(cartesian(input));
// TS
function* cartesianIterator<T>(items: T[][]): Generator<T[]> {
const remainder = items.length > 1 ? cartesianIterator(items.slice(1)) : [[]];
for (let r of remainder) for (let h of items.at(0)!) yield [h, ...r];
}
// get values:
const cartesian = <T>(items: T[][]) => [...cartesianIterator(items)];
console.log(cartesian(input));
You could take an iterative approach by building sub arrays.
var parts = [[0, 1], [0, 1, 2, 3], [0, 1, 2]],
result = parts.reduce((a, b) => a.reduce((r, v) => r.concat(b.map(w => [].concat(v, w))), []));
console.log(result.map(a => a.join(', ')));
.as-console-wrapper { max-height: 100% !important; top: 0; }
After doing a little research I discovered a previous related question:
Finding All Combinations of JavaScript array values
I've adapted some of the code from there so that it returns an array of arrays containing all of the permutations:
function(arraysToCombine) {
var divisors = [];
for (var i = arraysToCombine.length - 1; i >= 0; i--) {
divisors[i] = divisors[i + 1] ? divisors[i + 1] * arraysToCombine[i + 1].length : 1;
}
function getPermutation(n, arraysToCombine) {
var result = [],
curArray;
for (var i = 0; i < arraysToCombine.length; i++) {
curArray = arraysToCombine[i];
result.push(curArray[Math.floor(n / divisors[i]) % curArray.length]);
}
return result;
}
var numPerms = arraysToCombine[0].length;
for(var i = 1; i < arraysToCombine.length; i++) {
numPerms *= arraysToCombine[i].length;
}
var combinations = [];
for(var i = 0; i < numPerms; i++) {
combinations.push(getPermutation(i, arraysToCombine));
}
return combinations;
}
I've put a working copy at http://jsfiddle.net/7EakX/ that takes the array you gave earlier ([[0,1], [0,1,2,3], [0,1,2]]) and outputs the result to the browser console.
const charSet = [["A", "B"],["C", "D", "E"],["F", "G", "H", "I"]];
console.log(charSet.reduce((a,b)=>a.flatMap(x=>b.map(y=>x+y)),['']))
Just for fun, here's a more functional variant of the solution in my first answer:
function cartesian() {
var r = [], args = Array.from(arguments);
args.reduceRight(function(cont, factor, i) {
return function(arr) {
for (var j=0, l=factor.length; j<l; j++) {
var a = arr.slice(); // clone arr
a[i] = factor[j];
cont(a);
}
};
}, Array.prototype.push.bind(r))(new Array(args.length));
return r;
}
Alternative, for full speed we can dynamically compile our own loops:
function cartesian() {
return (cartesian.cache[arguments.length] || cartesian.compile(arguments.length)).apply(null, arguments);
}
cartesian.cache = [];
cartesian.compile = function compile(n) {
var args = [],
indent = "",
up = "",
down = "";
for (var i=0; i<n; i++) {
var arr = "$"+String.fromCharCode(97+i),
ind = String.fromCharCode(105+i);
args.push(arr);
up += indent+"for (var "+ind+"=0, l"+arr+"="+arr+".length; "+ind+"<l"+arr+"; "+ind+"++) {\n";
down = indent+"}\n"+down;
indent += " ";
up += indent+"arr["+i+"] = "+arr+"["+ind+"];\n";
}
var body = "var res=[],\n arr=[];\n"+up+indent+"res.push(arr.slice());\n"+down+"return res;";
return cartesian.cache[n] = new Function(args, body);
}
var f = function(arr){
if(typeof arr !== 'object'){
return false;
}
arr = arr.filter(function(elem){ return (elem !== null); }); // remove empty elements - make sure length is correct
var len = arr.length;
var nextPerm = function(){ // increase the counter(s)
var i = 0;
while(i < len)
{
arr[i].counter++;
if(arr[i].counter >= arr[i].length){
arr[i].counter = 0;
i++;
}else{
return false;
}
}
return true;
};
var getPerm = function(){ // get the current permutation
var perm_arr = [];
for(var i = 0; i < len; i++)
{
perm_arr.push(arr[i][arr[i].counter]);
}
return perm_arr;
};
var new_arr = [];
for(var i = 0; i < len; i++) // set up a counter property inside the arrays
{
arr[i].counter = 0;
}
while(true)
{
new_arr.push(getPerm()); // add current permutation to the new array
if(nextPerm() === true){ // get next permutation, if returns true, we got them all
break;
}
}
return new_arr;
};
Here's another way of doing it. I treat the indices of all of the arrays like a number whose digits are all different bases (like time and dates), using the length of the array as the radix.
So, using your first set of data, the first digit is base 2, the second is base 4, and the third is base 3. The counter starts 000, then goes 001, 002, then 010. The digits correspond to indices in the arrays, and since order is preserved, this is no problem.
I have a fiddle with it working here: http://jsfiddle.net/Rykus0/DS9Ea/1/
and here is the code:
// Arbitrary base x number class
var BaseX = function(initRadix){
this.radix = initRadix ? initRadix : 1;
this.value = 0;
this.increment = function(){
return( (this.value = (this.value + 1) % this.radix) === 0);
}
}
function combinations(input){
var output = [], // Array containing the resulting combinations
counters = [], // Array of counters corresponding to our input arrays
remainder = false, // Did adding one cause the previous digit to rollover?
temp; // Holds one combination to be pushed into the output array
// Initialize the counters
for( var i = input.length-1; i >= 0; i-- ){
counters.unshift(new BaseX(input[i].length));
}
// Get all possible combinations
// Loop through until the first counter rolls over
while( !remainder ){
temp = []; // Reset the temporary value collection array
remainder = true; // Always increment the last array counter
// Process each of the arrays
for( i = input.length-1; i >= 0; i-- ){
temp.unshift(input[i][counters[i].value]); // Add this array's value to the result
// If the counter to the right rolled over, increment this one.
if( remainder ){
remainder = counters[i].increment();
}
}
output.push(temp); // Collect the results.
}
return output;
}
// Input is an array of arrays
console.log(combinations([[0,1], [0,1,2,3], [0,1,2]]));
You can use a recursive function to get all combinations
const charSet = [["A", "B"],["C", "D", "E"],["F", "G", "H", "I"]];
let loopOver = (arr, str = '', final = []) => {
if (arr.length > 1) {
arr[0].forEach(v => loopOver(arr.slice(1), str + v, final))
} else {
arr[0].forEach(v => final.push(str + v))
}
return final
}
console.log(loopOver(charSet))
This code can still be shorten using ternary but i prefer the first version for readability 😊
const charSet = [["A", "B"],["C", "D", "E"],["F", "G", "H", "I"]];
let loopOver = (arr, str = '') => arr[0].map(v => arr.length > 1 ? loopOver(arr.slice(1), str + v) : str + v).flat()
console.log(loopOver(charSet))
Another implementation with ES6 recursive style
Array.prototype.cartesian = function(a,...as){
return a ? this.reduce((p,c) => (p.push(...a.cartesian(...as).map(e => as.length ? [c,...e] : [c,e])),p),[])
: this;
};
console.log(JSON.stringify([0,1].cartesian([0,1,2,3], [[0],[1],[2]])));

Loop Through Nested Array Elements With JavaScript

I'm trying to loop through nested arrays to determine if an element in the array is either "open" or "senior":
function openOrSenior(data) {
for (let i = 0; i <= data.length; i++) {
let dataElement = data[i];
for (let j = 0; j <= dataElement.length; j++) {
if (dataElement[0] >= 55 && dataElement[1] > 7) {
return ["Senior"];
}
return ["Open"];
}
}
}
Given the input of
[[18, 20],[45, 2],[61, 12],[37, 6],[21, 21],[78, 9]]
The function should output
["Open", "Open", "Senior", "Open", "Open", "Senior"]
But currently it looks like it's only looping through the first element in the main array ([18, 20]) because my function is only returning:
["Open"]
Why is this function failing to continue to loop through the other nested arrays and return either "Open" or "Senior"? Possibly a problem with the scope?
https://www.codewars.com/kata/categorize-new-member/train/javascript
I was trying to implement what I found here, which suggested a for-loop within a for-loop.
You are returning whenever the check succeeds or not, and you've got a redundant for loop. You should iterate the array with a single for loop, and according to the check push Senior or Open to the result array. In the end return the result array.
function openOrSenior(data) {
const result = [];
for (let i = 0; i < data.length; i++) {
const dataElement = data[i];
if (dataElement[0] >= 55 && dataElement[1] > 7) {
result.push("Senior");
} else result.push("Open");
}
return result;
}
console.log(openOrSenior([[18, 20],[45, 2],[61, 12],[37, 6],[21, 21],[78, 9]]));
Or you can use Array.map():
const openOrSenior = data =>
data.map(([a, b]) =>
a >= 55 && b > 7 ? 'Senior' : 'Open'
)
console.log(openOrSenior([[18, 20],[45, 2],[61, 12],[37, 6],[21, 21],[78, 9]]))
You need only a single loop and an array for the values.
function openOrSenior(data) {
var result = [];
for (let i = 0; i < data.length; i++) {
let [left, right] = data[i];
result.push(left >= 55 && right > 7
? "Senior"
: "Open"
);
}
return result;
}
console.log(openOrSenior([[18, 20], [45, 2], [61, 12], [37, 6], [21, 21], [78, 9]]));

Check if an array is descending, ascending or not sorted?

I'm just beginning with programming using javascript and I need to practice some questions to get EXP with the logic of code build.
I got this question for homework but I can't make it work for some reason, even though it seems "logic" to me.
Check if an array is descending, ascending or not sorted using loops.
I'm just a noob so please try and help me figure this out as I only got to loops in my studies (:
this is the code I wrote:
var array = [1, 2, 3, 7 ];
var d = 0;
var c =0 ;
var b = 1;
var a = 0;
for (var i = 1; i <= array.length; i++)
{
if (array[c]<array[b] && a!== -1 ){
d = -1;
c =c+1;
b = b+1;
if(c==array.length){
console.log("asc");
break;
}else{
continue;
}
} else if (array[c]>array[b] && d!==-1 ){
a = -1;
d= d+1;
b = b+1;
if(i=array.length){
console.log("dsc");
break;
}else{continue;}
} else{
console.log("unsorted array");
break;
}
}
Array.prototype.every passes its predicate an index, which you can use to get an element’s predecessor:
function isAscending(arr) {
return arr.every(function (x, i) {
return i === 0 || x >= arr[i - 1];
});
}
Here, we’re checking that every item (x) is greater than or equal to the item before it (arr[i - 1]) or has no item before it (i === 0).
Flip >= to <= for isDescending.
"Check if an array is descending, ascending or not sorted using loops"
// define the array
var array = [1,2,3,7];
// keep track of things
var isDescending = true;
var isAscending = true;
// we're looking ahead; loop from the first element to one before the last element
for (var i=0, l=array.length-1; i<l; i++)
{
////////////////////////////////////////////////////////////
// log to the console to show what's happening for each loop iteration
// this is the ith iteration
console.log("loop iteration %s", i);
// breaking isDescending down:
// is this value greater than the next value?
console.log("A: (%s > %s) = %s", array[i], array[i+1], (array[i] > array[i+1]));
// have all values been descending so far?
console.log("B: isDescending: %s", isDescending);
// if this value is greater than the next and all values have been descending so far, isDescending remains true. Otherwise, it's set to false.
console.log("are A and B both true? %s", (isDescending && (array[i] > array[i+1])));
// add a line break for clarity
console.log("");
////////////////////////////////////////////////////////////
// true if this is greater than the next and all other so far have been true
isDescending = isDescending && (array[i] > array[i+1]);
// true if this is less than the next and all others so far have been true
isAscending = isAscending && (array[i] < array[i+1]);
}
if (isAscending)
{
console.log('Ascending');
}
else if (isDescending)
{
console.log('Descending');
}
else
{
console.log('Not Sorted');
}
This is a question that requires some sort of loop, with several if statements because there are several cases you need to tackle:
Array is empty or has only one element.
All items in the array are equal
Array is ascending - delta between 2 elements > 0, but some deltas may be 0
Array is descending - delta between 2 elements < 0, but some deltas may be 0
Not sorted - some deltas are > 0, and some are < 0
Depending on how the sorted is defined in the question, cases 1 & 2 might be regarded as unsorted as well.
function findSortOrder(arr) {
if(arr.length < 2) { // case 1
return 'not enough items'; // can also be 'unsorted'
}
var ascending = null;
var nextArr = arr.slice(1); // create an array that starts from the 2nd element of the original array
for(var i = 0; i < nextArr.length; i++) {
if (nextArr[i] === arr[i]) { // neutral - do nothing
} else if(ascending === null) { // define the the direction by the 1st delta encountered
ascending = nextArr[i] > arr[i];
} else if (ascending !== nextArr[i] > arr[i]) { // case 5
return 'unsorted';
}
}
if(ascending === null) { // case 2
return 'all items are equal'; // can also be 'unsorted'
}
return ascending ? 'ascending' : 'descending'; // cases 3 & 4
}
console.log(findSortOrder([1])); // case 1
console.log(findSortOrder([1, 1, 1, 1])); // case 2
console.log(findSortOrder([1, 1, 2, 3, 7, 7])); // case 3
console.log(findSortOrder([7, 2, 2, 1])); // case 4
console.log(findSortOrder([7, 2, 1, 3, 2, 1])); // case 5
You could use a copy from the second element and check the predecessor for the wanted sort order.
function checkArray(array) {
var aa = array.slice(1);
if (!aa.length) {
return "Just one element";
}
if (aa.every((a, i) => array[i] > a)) {
return "Ascending";
}
if (aa.every((a, i) => array[i] < a)) {
return "Descending";
}
return "Unsorted";
}
console.log(checkArray([1, 2, 3, 4, 5]));
console.log(checkArray([5, 4, 3, 2, 1]));
console.log(checkArray([3, 1, 4, 2, 5]));
console.log(checkArray([42]));
function isAscending(arr = []) {
for (let i = 0; i < arr.length; i++) {
if (arr[i + 1] <= arr[i]) {
return false;
}
}
return true;
}
function isAscending(arr) {
return arr
.slice(1)
.every((num,i) => num >= arr[i]);
}
console.log(isAscending([1,2,3])); // true
console.log(isAscending([12,38,25])); // false
console.log(isAscending([103,398,52,629])); // false
arr.slice(1) --> allows us to start iteration at index 1 instead of 0
we'll iterate over "arr" with "every" & compare the current "num" against the previous "num" with "arr[i]"
function findOrder(array) {
var asc = true;
var desc = true;
if(array.length < 2){
return 'array is too small'
}
for(var i=1, len=array.length;i<len;i++){
//if current element is bigger than previous array is not descending
if(array[i]>array[i-1]){
desc = false;
//if current element is smaller than previous array is not ascending
}else if(array[i]<array[i-1]){
asc = false;
}
if(!asc && !desc){
return 'not sorted'
}
}
if(asc && desc){
return 'array values are equal'
}else if (asc){
return 'array is ascending'
}else {
return 'array is descending'
}
}
Actually we may do even more by creating an Array method like natureOf which can tell us more about the nature of the array than just ascending, descendig or flat. Array.natureOf() shall give us a value between -1 and 1. If it is -1 the array is fully descending and 1 would mean fully ascending of course. Any value inbetween would give us the inclination of the array. As you would guess 0 would mean totally random or flat. (it's fairly easy to insert the logic to distinguish random from flat if that's also needed)
Array.natureOf = function(a){
var nature = a.reduce((n,e,i,a) => i && a[i-1] !== e ? a[i-1] < e ? (n.asc++, n)
: (n.dsc++, n)
: n, {asc:0, dsc:0});
return (nature.asc - nature.dsc) / (a.length-1);
};
var arr = [1,2,3,4,5,6,7,8,9,10,7,11,13,14,15],
brr = Array.from({length:2000000}, _ => ~~(Math.random()*1000000000));
console.log(`The nature of "arr" array is ${Array.natureOf(arr)}`);
console.log(`The nature of "brr" array is ${Array.natureOf(brr)}`);
console.log(checkSort([1, 2, 3, 3, 4, 5]));
console.log(checkSort([5, 4, 3, 2, 1, 1]));
console.log(checkSort([2, 5, 8, 9, 4, 6]));
function checkSort(arr){
var isDescending, isAscending;
isDescending = isAscending = true;
const len = arr.length - 1;
for (var index = 0 ; index < len ; index++){
if(isAscending)
isAscending = arr[index] <= arr[index + 1];// '<=' so as to check for same elements
if(isDescending)
isDescending = arr[index] >= arr[index + 1];//'<=' so as to check for same elements
}
var result = "Array is ";
if (isAscending)
return result.concat("sorted in ascending order");
if (isDescending)
return result.concat("sorted in descending order");
return result.concat("not sorted");
const isAscending=(arr)=>{
for(let i=0;i<arr.length;i++){
if(arr[i+1]<arr[i]){ return false } } return true }

deleting duplicates on sorted array

Just in case you missed, the question is about deleting duplicates on a sorted array. Which can be applied very fast algorithms (compared to unsorted arrays) to remove duplicates.
You can skip this if you already know how deleting duplicates on SORTED arrays work
Example:
var out=[];
for(var i=0,len=arr.length-1;i<len;i++){
if(arr[i]!==arr[i+1]){
out.push(arr[i]);
}
}
out.push(arr[i]);
See?, it is very fast. I will try to explain what just happened.
The sorted arrays *could look like this:
arr=[0,1,1,2,2,3,4,5,5,6,7,7,8,9,9,9];
*the sorting could be ASC or DESC, or by other weird methods, but the important thing is that every duplicated item is next each other.
We stopped at array.length-1 because we don't have anything to check with
Then we added the last element regardless of anything because:
case A:
... ,9,9,9];//we have dup(s) on the left of the last element
case B:
... ,7,9,10];//we don't have dup(s) on the left of the last element
If you really understand what is happening, you will know that we haven't added any 9 on the case A. So because of that, we want to add the last element no matter if we are on case A or B.
Question:
That explained, I want to do the same, but ignoring the undefined value on cases like:
var arr=[];arr[99]=1;//0 through 98 are undefined, but do NOT hold the undefined value
I want to remove those. And on the case I have some real undefined values, these should not be removed.
My poor attempt is this one:
var out=[];
for (var i=0,len=arr.length; i < len - 1;) {
var x = false;
var y = false;
for (var j = i, jo; j < len - 1; j++) {
if (j in arr) {
x = true;
jo = arr[j];
i = j + 1;
break;
}
}
if (x == false) {
break;
}
for (var u = i, yo; u < len - 1; u++) {
if (u in arr) {
y = true;
yo = arr[u];
i = u + 1;
break;
}
}
if (y == false) {
out.push(jo);
break;
}
if (jo !== yo) {
out.push(jo);
}
}
out.push(arr[len - 1]);
I am really lost, any help is appreciated
A modern one-liner using .filter()
arr.filter((e, i, a) => e !== a[i - 1]);
I'm very surprised by the complexity of other answers here, even those that use .filter()
Even using old-school ES5 syntax with no arrow functions:
arr.filter(function (e, i, a) { return e !== a[i - 1] });
Example:
let a = [0, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 7, 8, 9, 9, 9];
let b = arr.filter((e, i, a) => e !== a[i - 1]);
console.log(b); // [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
If you need to mutate the array in place then just use:
arr = arr.filter((e, i, a) => e !== a[i - 1]);
Personally I would recommend against using such complex solutions as the ones in other answers here.
For a start, I'm not entirely certain your original code is kosher. It appears to me that it may not work well when the original list is empty, since you try to push the last element no matter what. It may be better written as:
var out = [];
var len = arr.length - 1;
if (len >= 0) {
for (var i = 0;i < len; i++) {
if (arr[i] !== arr[i+1]) {
out.push (arr[i]);
}
}
out.push (arr[len]);
}
As to your actual question, I'll answer this as an algorithm since I don't know a lot of JavaScript, but it seems to me you can just remember the last transferred number, something like:
# Set up output array.
out = []
# Set up flag indicating first entry, and value of last added entry.
first = true
last = 0
for i = 0 to arr.length-1:
# Totally ignore undefined entries (however you define that).
if arr[i] is defined:
if first:
# For first defined entry in list, add and store it, flag non-first.
out.push (arr[i])
last = arr[i]
first = false
else:
# Otherwise only store if different to last (and save as well).
if arr[i] != last:
out.push (arr[i])
last = arr[i]
This is a one-liner:
uniquify( myArray.filter(function(x){return true}) )
If you don't already have uniquify written (the function you wrote to remove duplicates), you could also use this two-liner:
var newArray = [];
myArray.forEach(function(x) {
if (newArray.length==0 || newArray.slice(-1)[0]!==x)
newArray.push(x)
})
Elaboration:
var a=[];
a[0]=1; a[1]=undefined; a[2]=undefined;
a[10]=2; a[11]=2;
According to OP, array has "five elements" even though a.length==12. Even though a[4]===undefined, it is not an element of the array by his definition, and should not be included.
a.filter(function(x){return true}) will turn the above array into [1, undefined, undefined, 2, 2].
edit: This was originally written with .reduce() rather than .forEach(), but the .forEach() version is much less likely to introduce garbage-collector and pass-by-value issues on inefficient implements of javascript.
For those concerned about compatibility with the 6-year-old MIE8 browser, which does not support the last two editions of the ECMAScript standard (and isn't even fully compliant with the one before that), you can include the code at https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach However if one is that concerned about browser compatibility, one ought to program via a cross-compiler like GWT. If you use jQuery, you can also rewrite the above with only a few extra characters, like $.forEach(array, ...).
Perhaps something like this:
var out = [],
prev;
for(var i = 0; i < arr.length; i++) {
if (!(i in arr))
continue;
if (arr[i] !== prev || out.length === 0) {
out.push(arr[i]);
prev = arr[i];
}
}
The out.length check is to allow for the first defined array element having a value of undefined when prev also starts out initially as undefined.
Note that unlike your original algorithm, if arr is empty this will not push an undefined value into your out array.
Or if you have a new enough browser, you could use the Array.forEach() method, which iterates only over array elements that have been assigned a value.
An explicit way would be to pack the array (remove the undefined) values and use your existing algorithm for the duplicates on that..
function pack(_array){
var temp = [],
undefined;
for (i=0, len = _array.length; i< len; i++){
if (_array[i] !== undefined){
temp.push(_array[i]);
}
}
return temp;
}
I think this is what you want. It's a pretty simple algorithm.
var out = [], previous;
for(var i = 0; i < arr.length; i++) {
var current = arr[i];
if(!(i in arr)) continue;
if(current !== previous) out.push(current);
previous = arr[i];
}
This will run in O(N) time.
A very simple function, the input array must be sorted:
function removeDupes(arr) {
var i = arr.length - 1;
var o;
var undefined = void 0;
while (i > 0) {
o = arr[i];
// Remove elided or missing members, but not those with a
// value of undefined
if (o == arr[--i] || !(i in arr)) {
arr.splice(i, 1);
}
}
return arr;
}
It can probably be more concise, but might become obfuscated. Incidentally, the input array is modified so it doesn't need to return anything but it's probably more convenient if it does.
Here's a forward looping version:
function removeDupes2(arr) {
var noDupes = [],
o;
for (var i=0, j=0, iLen=arr.length; i<iLen; i++) {
o = arr[i];
if (o != noDupes[j] && i in arr) {
noDupes.push(o);
j = noDupes.length - 1;
}
}
return noDupes;
}
PS
Should work on any browser that supports javascript, without any additional libraries or patches.
This solution removes duplicates elements in-place. not recommended for functional programming
const arr =[0,0,1,1,2,2,2,3,4,5,5,6,7,7,8,9,9,9];
const removeDuplicates = (nums) => {
nums.forEach((element, idx) => {
nums.splice(idx, nums.lastIndexOf(element) - idx)
})
}
removeDuplicates(arr)
console.log(arr);
//sort the array
B.sort(function(a,b){ return a - b});
//removing duplicate characters
for(var i=0;i < B.length; i ++){
if(B[i]==B[i + 1])
B.splice(i,1)
}
if element in next index and current position is same remove the element at
current position
splice(targetPosition,noOfElementsToBeRemoved)
I believe what you are trying to achieve is not quite possible, but I could be wrong.
It's like one of those classic CS problems like the one where a barber in a village only shaves the one who don't shave themselves.
If you set the value of an array's index item as undefined, it's not really undefined.
Isn't that the case? A value can only be undefined when it hasn't been initialized.
What you should be checking for is whether a value is null or undefined. If null or duplicate skip the value, else retain it.
If null values and duplicates are what you are trying to skip then below function will do the trick.
function removeDuplicateAndNull(array){
if(array.length==0)
return [];
var processed = [], previous=array[0];
processed.push(array[0]);
for(var i = 1; i < array.length; i++) {
var value = array[i];
if( typeof value !== 'undefined' && value ==null)
continue;
if(value !== previous || typeof value === 'undefined')
processed.push(value);
previous = array[i];
}
return processed;
}
Test cases:
array=[,5,5,6,null,7,7] output =[ ,5,6,7]
array=[ 5,5,,6,null,,7,7] output=[5,,6,,7]
array=[7,7,,] output=[7,]
But even with this function there's a caveat. IF you check third test, the output is [7,]
instead of [7,,] !
If you check the length of the input and output arrays, array.length =3 and output.length=2.
The caveat is not with the function but with JavaScript itself.
This code is written in javascript. Its very simple.
Code:
function remove_duplicates(arr) {
newArr = [];
if (arr.length - 1 >= 0) {
for (i = 0; i < arr.length - 1; i++) {
// if current element is not equal to next
// element then store that current element
if (arr[i] !== arr[i + 1]) {
newArr.push(arr[i]);
}
}
newArr.push(arr[arr.length - 1]);
}
return newArr
}
arr=[0,1,1,2,2,3,4,5,5,6,7,7,8,9,9,9];
console.log(remove_duplicates(arr));
Here is the simple JavaScript solution without using any extra space.
function removeDuplicates(A) {
let i = 0;
let j = i + 1;
while (i < A.length && j < A.length) {
if (A[i] === A[j]) {
A.splice(i, 1);
j=i+1;
} else {
i++;
j++;
}
}
return A;
}
console.log('result', removeDuplicates([0,1,1,2,2,2,2,3,4,5,6,6,7]))
You can try the simple way
function hello(a: [], b: []) {
return [...a, ...b];
}
let arr = removeDuplicates(hello([1, 3, 7], [1, 5, 10]));
arr = removeDuplicates(arr);
function removeDuplicates(array) {
return array.filter((a, b) => array.indexOf(a) === b);
}
let mainarr = arr.sort((a, b) => parseInt(a) - parseInt(b));
console.log(mainarr); //1,3,5,7,10
One liner code
[1,3,7,1,5,10].filter((a, b) => [1,3,7,1,5,10].indexOf(a) === b).sort((a, b) => parseInt(a) - parseInt(b))
Here is simple solution to remove duplicates from sorted array.
Time Complexity O(n)
function removeDuplicate(arr) {
let i=0;
let newArr= [];
while(i < arr.length) {
if(arr[i] < arr[i+1]) {
newArr.push(arr[i])
} else if (i === (arr.length-1)) {
newArr.push(arr[i])
}
i++;
}
return newArr;
}
var arr = [1,2,3,4,4,5,5,5,6,7,7]
console.log(removeDuplicate(arr))
Let's suppose that you have a sorted array and you can't use additional array to find and delete duplicates:
In Python
def findDup(arr, index=1, _index=0):
if index >= len(arr):
return
if arr[index] != arr[_index]:
findDup(arr, index+1, _index+1)
if arr[index] == arr[_index]:
arr = deletedup(arr, index)
findDup(arr, index, _index) #Has to remain same here, because length has changed now
def deletedup(arr, del_index):
del arr[del_index]
return arr
arr = [1, 2, 3, 4, 4, 4, 5, 6, 7, 7, 7, 7, 7]
findDup(arr)
print arr

Categories

Resources