I need to print the duplicates from an array.
For example, given the following array and index, the function will print 6,23,33,100.
var array = [3,6,67,6,23,11,100,8,93,0,17,24,7,1,33,45,28,33,23,12,99,100];
Apparently we need to do it using two 'while loops'.
Im looking for a solution, but more importantly an explanation.
Links are very much appreciated.
Thanks!
The most elegant and efficient solution is to use a while loop which iterates the array only once, so, we have O(N) complexity.
For this, we need to declare an hash which keeps the number of occurencies for each array's item. If we found a duplicate one then we store it in duplicates array.
var arr = [3,6,67,6,23,11,100,8,93,0,17,24,7,1,33,45,28,33,23,12,99,100], i = 0, hash = {}, duplicates = [];
while(i < arr.length){
hash[arr[i]] = hash[arr[i]] ? hash[arr[i]] += 1 : 1;
if (hash[arr[i]] === 2)
duplicates.push(arr[i])
i++;
}
console.log(duplicates)
You could use the filter() and indexOf() methods.
var array = [3,6,67,6,23,11,100,8,93,0,17,24,7,1,33,45,28,33,23,12,99,100];
console.log(array.filter((a,b,c) => c.indexOf(a) !== b));
a -> is the value being passed in the arrow function.
b -> is the index being passed in.
c -> is the whole array being passed in.
This line is filtering the array based on, if the original array has a value (argument a) whose index does not match the given index passed in through the arrow function (argument b).
A good sample and explanation can be found here... W3Resource
Futhermore to assist in understanding the two major components of the code the Object...
Working with objects - Javascipt
and Arrays...Javascipt Arrays
For the shortest approach, you could take a closure
(s => )( )
with a Set
(s => )(new Set)
and a check. If a value is already seen, then take this value
(s => v => s.has(v) )(new Set)
or add the value to the set and return false, because a not seen value should not in the result set.
(s => v => !s.add(v))(new Set)
var array = [3, 6, 67, 6, 23, 11, 100, 8, 93, 0, 17, 24, 7, 1, 33, 45, 28, 33, 23, 12, 99, 100],
duplicates = array.filter((s => v => s.has(v) || !s.add(v))(new Set));
console.log(duplicates);
I saw this interesting post yesterday, and thought it'd be important to know how to create a 2D array from sorting the given argument:
How to get even numbers array to print first instead of odds?
Below is the code snippet from Ori Drori.
I was curious to know what line of code, and which expression sorts the data and creates 2D array. I assume it's something to do with [numbersArray[i] % 2], but isn't the remainder operator returns the remainder left over?
Also it's a bit confusing as it just set one bracket for an array and use push() to make 2 different arrays.
Any reference that'd help me to understand this will also be much appreciated- thanks!
var numbersArray = [1,2,34,54,55,34,32,11,19,17,54,66,13];
function divider(numbersArray) {
var evensOdds = [[], []];
for (var i = 0; i < numbersArray.length; i++) {
evensOdds[numbersArray[i] % 2].push(numbersArray[i]);
}
return evensOdds;
}
console.log(divider(numbersArray));
evensOdds has 2 array elements. evensOdds[0] represents first array, which will hold even nums. evensOdds[1] is second element and will hold odd numbers.
When you % 2 an even number, it will result in 0 and 1 for odd number. So when iterating through the array, you % 2, which will return 0 or 1 which enables you to access the first or second array in your evensOdds array and insert it.
The resulting arrays are not sorted but does represent the split between even and odd numbers. To have a sorted results, you will need the following:
var numbersArray = [1,2,34,54,55,34,32,11,19,17,54,66,13];
function divider(numbersArray) {
var evensOdds = [[], []];
for (var i = 0; i < numbersArray.length; i++) {
evensOdds[numbersArray[i] % 2].push(numbersArray[i]);
}
return evensOdds.map(array=> array.sort((a,b)=>a-b));
}
console.log(divider(numbersArray));
In the shared code the evensOdds[numbersArray[i] % 2] line is the part that filter the numbers and inserts them in the respective array, using the indexes 0 and 1 returned from the numbersArray[i] % 2 expression:
If it returns 0 so it's an even number and it will be pushed in the first array otherwise if it returns 1 it's an odd number and will be pushed in the second array.
Another alternative:
Well you can simply use Array.filter() method to filter both evens and odds arrays:
Demo:
var numbersArray = [1, 2, 34, 54, 55, 34, 32, 11, 19, 17, 54, 66, 13];
var evens = numbersArray.filter(function(el) {
return el % 2 == 0;
});
var odds = numbersArray.filter(function(el) {
return el % 2 == 1;
});
console.log(evens);
console.log(odds);
I have the following simple array:
my_array = [1, 11, 44, 4]
I want to produce a new array consisting of the difference between these elements, so it would be:
diff_array = [10, 33, 40]
What's the best way of going about this?
You could use Array#reduce for iterating and take the absolute delta for pushing to the result array.
Basically you need array.length - 1 deltas and iteration. In this case 3. Reduce takes, if no start value is given, the first two elements and iterates the wanted length. And while it needs the last value for the delta, the last value is returned.
At the end, the returned value of reduce is discarded, becuase it is not used anymore.
1 11 44 4 values
\ / \ / \ /
10 33 40 Math.abs(delta)
var array = [1, 11, 44, 4],
result = [];
array.reduce(function (a, b) {
result.push(Math.abs(a - b));
return b;
});
console.log(result);
here is a simple solution with a plain old for loop
array = [1, 11, 44, 4]
diff = []
for(var i = 1 ; i < array.length ; i++){
diff.push(Math.abs(array[i] - array[i-1]))
}
basically you loop starting at the second element of the array ,, and subtract from from the prev and pushing to the new array .
use this function, pass it the input array, returns the required array.
function diff(array){
var out = []
for (var i = 0; i < array.length-1; i++) {
out.push(Math.abs(array[i+1]-array[i]))
}
return out;
}
Normally one can do this with .reduce() but just for fun lets get some functional.
var myArray = [1, 11, 44, 4],
diff = a => a.length > 1 ? [Math.abs(a[1]-a[0])].concat(diff(a.slice(1))) : [];
console.log(diff(myArray));
Note: The above code is just for demonstration purposes. In your daily JS life you shouldn't do things like this. Use a whatever loop you like but never use recursion in your JS code. You want to see what i mean? Feed this array.
var myArray = Array(1000000).fill().map(_ => ~~(Math.random()*100+1));
It will beautifully crash your browser's tab. Peah..!
What would be the tersest way to create this array:
var x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
For example, a for loop:
var x = [];
for (var i=1;i<=20;i++) {
x.push(i);
}
Or a while loop:
var x = [], i = 1, endInt = 20;
while (i <= endInt) {
x.push(i);
i++;
}
Would there be other examples that would be terser -- in other words -- less code? I'm thinking of things like in Ruby where the equivalent code I believe would be as simple as 1..20. I'm not aware of syntax like that in JavaScript but I'm wondering if there are shorter ways to do that same thing.
UPDATE: I wasn't thinking of removing semicolons or var for answers in the question, but I have to admit the question implies that. I am more curious about algorithms than shaving bytes. Sorry if I was unclear! Also, making it into a function is simple enough, just slap function range(start, end) { /* guts here */ } around it and you're there. The question is are there novel approaches to the "guts."
Favorite method
Update Sep13,2015:
Just came up with this new method which works with browsers which support the ES6 standard:
> Array(5).fill().map((x,i)=>i)
[0, 1, 2, 3, 4]
Note the above does a tiny bit of extra work (fills with undefined) but is relatively minor vis-a-vis the speedup you can achieve by using a for loop, and if you forget the .fill you may be confused why your array is mysteriously [empty x 5]. You can encapsulate the above as a custom function, or alternatively use a somewhat more intended method:
> Array.from(Array(5),(x,i)=>i)
[0, 1, 2, 3, 4]
You can of course directly go from that into whatever you want to do, like python's list comprehensions e.g. [i**2 for i in range(5)]:
> Array.from(Array(5), (_,i)=> i**2)
[0, 1, 4, 9, 16]
... or if you want to get more complicated...:
> Array.from(Array(5), (_,i)=> {
const R = /*some computation*/;
return /*etc*/;
});
[edit May,2021]: theoretically tersest way of defining such a function nowadays is f=i=>i?[...f(i-1),i]:[], where you replace f with range1 or whatever the name is, but which would be very slow (quadratic complexity) due to intermediate structures so should never be used. f=i=>i?f(i-1)&&x.push(i)&&x:x=[] is linear complexity but relies on abuse of notation and is unreadable and pollutes global variables as well. But, since defining arrow functions (which don't bind but rather inherit this) is pretty terse nowadays, you could just wrap the above solution:
const range1 = n=> Array.from(Array(n), (_,i)=> i+i);
// range1(5)==[1, 2, 3, 4, 5]
Circumstantially, the tersest way to do a range(N), if you already have a list lying around of exactly that length N, is just to map it: e.g. rather than do Array.from(Array(myArr.length), (_,i)=> i**2), you would just do myArr.map((_,i)=> i**2). (This has no side-effect unless you want it to.)
everything below is historical:
After thinking about it a bit, this is the shortest implementation of the standard range(N) function in JavaScript I could come up with:
function range1(i){return i?range1(i-1).concat(i):[]}
Note: Do not use this in production; it's O(N^2)
Contrast with current top-voted answer:
function range1(i){var x=[];var i=1;while(x.push(i++)<i){};return x}
Example:
> range1(5)
[1, 2, 3, 4, 5]
This is like the poster child for recursion, though I was expecting it to be longer until I thought of ternary-if-statement, which brings it down to 42 necessary characters.
Note that the "standard" range function returning [start,end) can be written by doing .concat(i-1).
Update: Ooh, I discovered an incredibly short version with ugly imperative syntax by abusing for loops, reverse-ordering, the fact that assignments return a value: for(y=[],i=20;y[--i]=i;){} consisting of only 25 characters (though you will want var y which you can insert into a for loop, and +1 if you don't want 0...19). While it is not shorter if you need to define a function, it is shorter than i?r(i-1).concat(i):[] if you do not need to make a function.
Added some performance profiling testcases: it seems that everything besides a standard in-order for-loop is 10x slower, at least on V8. https://jsperf.com/array-range-in-javascript
(Of course, none of this matters if you're programming in a functional style anyway and would hit every element with a function call anyway.)
It can be done with features from the ES6, currently only supported by Firefox thou. I found a compatibility table here: http://kangax.github.io/compat-table/es6/
Array.from(new Array(20), (x,i) => i+1)
If you want to have some other range then I guess you could do
Array.from(new Array(5), (x,i) => i+5)
Which would then be [5,6,7,8,9]
You can do this with a while loop where the push happens inside the condition.Array.push returns the length of the array, which happens to be the same as the value in this case. So, you can do the following:
x = []; //normally would use var here
i = 1; //normally would use var here
while(x.push(i++)<20){}
//at this point, x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
Condensed version (31 characters)
x=[];i=1;while(x.push(i++)<20);
jsFiddle example
while-- is the way to go
var a=[],b=10;while(b--)a[b]=b+1
returns [1,2,3,4,5,6,7,8,9,10]
explained with start & length
var array=[],length=20,start=5;while(length--)array[length]=length+start
returns [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]
want range?
explained with start & end
var array=[],end=30,start=25,a=end-start+1;while(a--)array[a]=end--
returns [25, 26, 27, 28, 29, 30]
for --
for(var a=[],b=20;b>0;b--,a[b]=b+1)
for++
for(var a=[],b=0;b<20;b++,a[b]=b+1)
WHY is this theway to go?
while -- is prolly the fastest loop;
direct setting is faster than push & concat;
[] is also faster than new Array(10);
it's not much longer code than all the others
byte saving techniques:
use the arguments as a placholder forthe in function variables
don't use new Array(),push(),concat() if not needed
place "(){};," only when needed.
use a,b,c,d... in short functions.
so if u want a function for this
with start,end (range)
function range(a,b,c,d){d=[];c=b-a+1;while(c--)d[c]=b--;return d}
so now range(3,7) returns [3,4,5,6,7]
u save bytes in many ways here and this function is also very fast as it does not use concat, push, new Array and it's made with a while --
If you're OK with 0-20, here are my latest favs from recent code golfing:
[...'0'.repeat(21)].map((_,i)=>i)
Array.from({length:21},(_,i)=>i)
Array(21).fill().map((_,i)=>i)
[...Array(21)].map((_,i)=>i)
Array(21).map((_,i)=>i)
[...Array(21).keys()]
Using ES6
numArr = Array(5).fill(0).reduce(arr=>{ arr.push(arr.length); return arr },[])
if you accept to have a counter starting from 0 instead of 1...
const zeroNineteen = [...Array(20).keys()];
// outputs [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]
if you really need it to start with 1:
const terserst = [...Array(21).keys()].slice(1);
it's 30 characters and yet readable, don't you think?
I can't think of a way with less characters than ~46:
var a=[];while(a.length<20)a.push(a.length+1);
Granted, you could make a function out of that.
Reading your comments about a function, you could do something like
var range = function (start, end) {
var arr = [];
while (start <= end) {
arr.push(start++)
}
return arr;
};
Then range(1, 20) would return the array as expected.
I suppose this is the shortest way:
var i=0, arr = [];
while (i++<20){
arr.push(i);
}
or associating on the 'perverse' code in EndangeredMassa's answer:
var i,arr; while (i=i||1, (arr=arr||[]).push(i++)<20){}
You could always create a function...
function createNumArray(a, b) {
var arr = [],
i = a;
while((arr[arr.length] = i) < b) {i++}
return arr;
}
Which allows you to write succinct code later on such as...
var arr = createNumArray(1, 20);
If you are looking to shave characters off anyway possible without regard for readability, this is the best I can do:
var x=[],i=0
while(i<20)
x[i]=i+++1
Not a lot better than yours though.
Edit:
Actually this works better and shaves off a couple characters:
var x=[],i=0
while(i<20)
x[i]=++i
Edit 2:
And here's my entry for a general "range" function in the least number of characters:
function range(s,e){var x=[];while(s<e+1)x.push(s++);return x}
Again, don't write code this way. :)
Array.from({length: n}).map((_, i) => i);
In my knowledge, the option of using for loop, as you mentioned, is the most tersest.
That is,
var x = [];
for (var i=1;i<=20;i++) {
x.push(i);
}
var i = 0;
var x = [];
while (i++ < 20) x.push(i);
JSFiddle
I'd extend Array's prototype to make it simple to access:
Array.prototype.range = function(start, end) {
if (!this.length) {
while (end >= start) {
this.push(start++);
}
} else {
throw "You can only call 'range' on an empty array";
}
return this;
};
var array = [].range(1, 20);
While the above is the nearest I can think of with respect to the syntactic sugar you're looking for, you may want to try out CoffeeScript.
It supports the notation you're after.
CoffeeScript:
test = [1..20]
alert test
Renders to JavaScript:
var test;
test = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
alert(test);
You can try out live examples on their site, and see the conversion it does as you type.
Just click the TRY COFFEESCRIPT link at the top, and you'll get a console where you can test some code.
There's always the IterableInt:
for (const z of new IterableInt(15)) {
// 15,14,13....3,2,1
}
implemented like so:
class IterableInt {
constructor(val) {
if (val < 0) {
throw new Error('cannot iterate over a negative number.')
}
this.val = val;
}
static create(val){
return new IterableInt(val);
}
[Symbol.iterator]() {
const self = this;
return {
next() {
const value = self.val--;
const done = value <= 0;
return {value, done}
}
}
}
}
to do things like:
for (const z of new IterableInt(3,15)) {
// 3,4,5...14,15
}
go to this gist:
https://gist.github.com/ORESoftware/1aca4ae704b355c45702d11c0e245776