How does the Javascript Array Push code work internally - javascript

What is the internal code logic for Push and Pop methods in javascript..?? How does Push method stores the values in Array.

The push and pop methods are intentionally generic, they only rely on the existance of a length property, and that they can add and remove properties.
The push method will read the length property, add a property with that name, and increase the length. Basically:
function push(value) {
var len = this.length;
this[len] = value;
len++;
this.length = len;
return len;
}
The pop method will read the length property, decrease it, get the property with that name and remove the property. Basically:
function pop() {
var len = this.length - 1;
var value = this[len];
this.length = len;
delete this[len];
return value;
}
The actual implementations are a bit more complex, as they support for example multiple parameters for the push method, and some more error checks. There might also implement special optimised code for when the object is actually an array, but then the generic code is still there for other objects.
The methods are intentionally generic so that they can be used on objects that aren't actually arrays. You can make your own object that supports them by just having a length property:
var o = {
length: 0,
push: Array.prototype.push,
pop: Array.prototype.pop
};
o.push(1);
var one = o.pop();
Demo: http://jsfiddle.net/Guffa/9r4gavzb/

We can try some tests and test behavior:
const arr1 = []
const { push: push1 } = arr
const arr2 = []
const { push: push2 } = arr
console.log(push1 === push2) // true
console.log(push1 === Array.prototype.push) // true
push1(1) // TypeError: Cannot convert undefined or null to object
push1.call(arr1, 1) // arr1: [1], arr2: []
push2.call(arr1, 2) // arr1: [1, 2], arr2: []
push1.bind(arr2)(1) // arr1: [1, 2], arr2: [1]
push.call(arr2, 2)
And we can say that push method uses this under the hood...

Related

Javascript - Loop through array backwards with forEach

Is there a way to loop backwards through an array using forEach (not any other kind of loop, I know how to do with with a for / standard ways) and without actually reversing the array itself?
let arr = [1, 2, 3];
arr.slice().reverse().forEach(x => console.log(x))
will print:
3
2
1
arr will still be [1, 2, 3], the .slice() creates a shallow copy.
There is a similar array method that has a reverse counter part, reduce comes together with reduceRight:
const array = ['alpha', 'beta', 'gamma'];
array.reduceRight((_, elem) => console.log(elem), null);
When using it for the requested purpose, make sure to provide a second argument. It can be null or anything else. Also note that the callback function has as first argument the accumulator, which you don't need for this purpose.
If including a library is an option:
Lodash: forEachRight.
Just use a for loop. Start at the end of the array and go backwards from there.
const array = ['blastoff', 1, 2, 3];
for (let index = array.length - 1; index >= 0; index--) {
const element = array[index];
console.log(element);
}
No, forEach only processes forward through the array. So you'd have to do something else, which you've said in your question was out of scope.
I can think of two options which just use precursors to using forEach (so, they don't use a for loop or other kind of loop). I don't know if those would be out of scope or not, so here they are:
Copy the array and reverse the copy, then use forEach on it
Use Object.keys to get the indexes, reverse that, then use forEach on it (which will loop through the indexes, not the values, but then we can look them up)
Here's #1:
slice copies the array (shallow copy, so not likely to be expensive), then we reverse it, then forEach:
var a = ['one', 'two', 'three'];
a.slice().reverse().forEach(function(entry) {
console.log(entry);
});
console.log("Proof that a is not, itself, reversed: " +
JSON.stringify(a));
Here's #2:
We use Object.keys to get the array indices (using filter if you store non-element properties in your arrays), reverse that, and then loop through the result:
var a = ['one', 'two', 'three'];
Object.keys(a).reverse().forEach(function(index) {
console.log(a[index]);
});
console.log("Proof that a is not, itself, reversed: " +
JSON.stringify(a));
Side note: Here's what I mean about using filter if you have non-element properties on your array:
var a = ['one', 'two', 'three'];
a.nonElementProperty = "foo";
Object.keys(a).filter(function(name) {
return String(+name) === name;
}).reverse().forEach(function(index) {
console.log(a[index]);
});
console.log("Proof that a is not, itself, reversed: " +
JSON.stringify(a));
As yet the browsers do not seem to have optimised the Array.forEach function. With not much effort you can write a simple polyfill that out performs the Array.forEach method by at least 10 to 1.
So you can create your own Array.revEach and have it outperform the native Array.forEach, thought I hope that the browsers address the very slow performance of Array.forEach soon and make the need to polyfill actual existing methods not necessary.
For Array.revEach out performs Array.forEach running 17 times faster on "Chrome 46.0.2490.22 beta-m"
if (Array.prototype.revEach === undefined) {
Object.defineProperty(Array.prototype, 'revEach', {
writable : false,
enumerable : false,
configurable : false,
value : function (func) {
var i;
var len = this.length-1;
for (i = len; i >= 0; i--) {
func(this[i], i, this);
}
}
});
}
Just to add the actual official polyfill modified to reverse. Comments show my changes.
// Production steps of ECMA-262, Edition 5, 15.4.4.18
// Reference: http://es5.github.io/#x15.4.4.18
// Modified by Blindman67 to revEach
if (!Array.prototype.revEach) { // name changed
Array.prototype.revEach = function(callback, thisArg) { // name changed
var T; // k defined where len was
if (this == null) {
throw new TypeError(' this is null or not defined');
}
var O = Object(this);
var k = (O.length >>> 0)-1; // set k (counter) ToUint32
// len var removed
if (typeof callback !== "function") {
throw new TypeError(callback + ' is not a function');
}
if (arguments.length > 1) {
T = thisArg;
}
while (k >= 0) { // reverse condition
var kValue;
if (k in O) {
kValue = O[k];
callback.call(T, kValue, k, O);
}
k--; // dec counter
}
};
}
array.forEach has 3 parameters. You can use these to effectively forEach backward.
var arr = [1, 2, 3];
arr.forEach(function(x, index, the_array) {
let x_prime = the_array[the_array.length-1-index]
console.log(x_prime);
})
will print
3
2
1
This can be accomplished relatively concisely using the reverse method, the forEach method, and (if using ES6) the arrow function
var someArray = ["a","b","c","d"];
someArray.reverse().forEach(arrayItem =>
console.log(arrayItem)
)
If you are not using ES6, the solution is about the same, just without the arrow function.
var someArray = ["a","b","c","d"];
someArray.reverse().forEach(function(arrayItem) {
console.log(arrayItem)
})
Both will print to the console:
d
c
b
a
There are many ways to achive this task.
Firsly we can use Array.reduceRight() method
[1,2,3,4,5].reduceRight((total,item) => {
console.log(item);
// Do somthing here and remember the return statement
return item;
},0)
Output: 5,4,3,2,1
the reduceRight method traverse an array in right to left manner and we can get advantage of it.
,but always keep in mind that you have to return something to keep going this loop until the length is reached.
As a second method we can use Array.reverse()
this method first format the array in reversed manner then returns it, and now you can iterate in reverse manner.
[1,2,3].reverse().map(n => console.log(n));
Output: 3,2,1
But the disadvantage of this method is that if you have thousands of entries in array then it may affect your performance.
Third and the most easiest way it to use classical for loop
let array = [1,2,3,4,5];
let start = array.length;
for(;start >= 0;start--){
// travese in right to left manner
console.log(array[start])
}
What about:
const array = [1, 2, 3];
const revArray = [...array].reverse() // won't affect the original array
revArray.forEach(x => console.log(x)) // 3, 2, 1
One liner:
[...array].reverse().forEach(x => console.log(x)) // 3, 2, 1
With index var:
[...array].reverse().forEach((val, index) => {
const revIndex = array.length - i - 1
console.log(revIndex) // 0, 1, 2
console.log(revIndex) // 2, 1, 0
console.log(val) // 3, 2, 1
})
You can also do it this way
let arr = [1, 3, 5, 7, 9];
arr.forEach(value => {
console.log(value);
})
let reversed = new Array(arr.reverse());
console.log("\n\nReversed: ");
reversed.forEach(value => {
value.forEach(val => {
console.log(val)
})
})

How to implement a map or sorted-set in javascript

Javascript has arrays which use numeric indexes ["john", "Bob", "Joe"] and objects which can be used like associative arrays or "maps" that allow string keys for the object values {"john" : 28, "bob": 34, "joe" : 4}.
In PHP it is easy to both A) sort by values (while maintaining the key) and B) test for the existence of a value in an associative array.
$array = ["john" => 28, "bob" => 34, "joe" => 4];
asort($array); // ["joe" => 4, "john" => 28, "bob" => 34];
if(isset($array["will"])) { }
How would you acheive this functionality in Javascript?
This is a common need for things like weighted lists or sorted sets where you need to keep a single copy of a value in data structure (like a tag name) and also keep a weighted value.
This is the best I've come up with so far:
function getSortedKeys(obj) {
var keys = Object.keys(obj);
keys = keys.sort(function(a,b){return obj[a]-obj[b]});
var map = {};
for (var i = keys.length - 1; i >= 0; i--) {
map[keys[i]] = obj[keys[i]];
};
return map;
}
var list = {"john" : 28, "bob": 34, "joe" : 4};
list = getSortedKeys(list);
if(list["will"]) { }
Looking at this answer by Luke Schafer I think I might have found a better way to handle this by extending the Object.prototype:
// Sort by value while keeping index
Object.prototype.iterateSorted = function(worker, limit)
{
var keys = Object.keys(this), self = this;
keys.sort(function(a,b){return self[b] - self[a]});
if(limit) {
limit = Math.min(keys.length, limit);
}
limit = limit || keys.length;
for (var i = 0; i < limit; i++) {
worker(keys[i], this[keys[i]]);
}
};
var myObj = { e:5, c:3, a:1, b:2, d:4, z:1};
myObj.iterateSorted(function(key, value) {
console.log("key", key, "value", value)
}, 3);
http://jsfiddle.net/Xeoncross/kq3gbwgh/
With ES6 you could choose to extend the Map constructor/class with a sort method that takes an optional compare function (just like arrays have). That sort method would take two arguments, each of which are key/value pairs so that the sorting can happen on either the keys or the values (or both).
The sort method will rely on the documented behaviour of Maps that entries are iterated in insertion order. So this new method will visit the entries according to the sorted order, and then delete and immediately re-insert them.
Here is how that could look:
class SortableMap extends Map {
sort(cmp = (a, b) => a[0].localeCompare(b[0])) {
for (const [key, value] of [...this.entries()].sort(cmp)) {
this.delete(key);
this.set(key, value); // New keys are added at the end of the order
}
}
}
// Demo
const mp = new SortableMap([[3, "three"],[1, "one"],[2, "two"]]);
console.log("Before: ", JSON.stringify([...mp])); // Before
mp.sort( (a, b) => a[0] - b[0] ); // Custom compare function: sort numerical keys
console.log(" After: ", JSON.stringify([...mp])); // After
I'm not sure why none of these answers mentions the existence of a built-in JS class, Set. Seems to be an ES6 addition, perhaps that's why.
Ideally override either add or keys below... NB overriding keys doesn't even need access to the Set object's prototype. Of course you could override these methods for the entire Set class. Or make a subclass, SortedSet.
const mySet = new Set();
const mySetProto = Object.getPrototypeOf(mySet);
const addOverride = function(newObj){
const arr = Array.from(this);
arr.add(newObj);
arr.sort(); // or arr.sort(function(a, b)...)
this.clear();
for(let item of arr){
mySetProto.add.call(this, item);
}
}
mySet.add = addOverride;
const keysOverride = function(){
const arr = Array.from(this);
arr.sort(); // or arr.sort(function(a, b)...)
return arr[Symbol.iterator]();
}
mySet.keys = keysOverride;
Usage:
mySet.add(3); mySet.add(2); mySet.add(1); mySet.add(2);
for(let item of mySet.keys()){console.log(item)};
Prints out:
1 ... 2 ... 3
NB Set.keys() returns not the items in the Set, but an iterator. You could choose to return the sorted array instead, but you'd obviously be breaking the class's "contract".
Which one to override? Depends on your usage and the size of your Set. If you override both you will be duplicating the sort activity, but in most cases it probably won't matter.
NB The add function I suggest is of course naive, a "first draft": rebuilding the entire set each time you add could be pretty costly. There are clearly much cleverer ways of doing this based on examining the existing elements in the Set and using a compare function, a binary tree structure*, or some other method to determine where in it to add the candidate for adding (I say "candidate" because it would be rejected if an "identical" element, namely itself, were already found to be present).
The question also asks about similar arrangements for a sorted map... in fact it turns out that ES6 has a new Map class which lends itself to similar treatment ... and also that Set is just a specialised Map, as you might expect.
* e.g. https://github.com/Crizstian/data-structure-and-algorithms-with-ES6/tree/master/10-chapter-Binary-Tree
You usually don't sort an object. But if you do: Sorting JavaScript Object by property value
If you want to sort an array, let's say the following
var arraylist = [{"john" : 28},{ "bob": 34},{ "joe" : 4}];
You can always use Array.prototype.sort function.
Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
Maybe this code look like what you want:
Object.prototype.asort = function(){
var retVal = {};
var self = this;
var keys = Object.keys(this);
keys = keys.sort(function(a,b){return self[a] - self[b]});
for (var i = 0; i < keys.length; i++) {
retVal[keys[i]] = this[keys[i]];
}
return retVal;
}
var map = {"john" : 28, "bob": 34, "joe" : 4}
var sortedMap = map.asort();//sortedMap["will"]: undefined
If you use the open source project jinqJs its easy.
See Fiddler
var result = jinqJs()
.from([{"john" : 28},{ "bob": 34},{ "joe" : 4}])
.orderBy([{field: 0}])
.select();
Here's an implementation of OrderedMap.
Use the functions get() and set() to extract or push key value pairs to the OrderedMap.
It is internally using an array to maintain the order.
class OrderedMap {
constructor() {
this.arr = [];
return this;
}
get(key) {
for(let i=0;i<this.arr.length;i++) {
if(this.arr[i].key === key) {
return this.arr[i].value;
}
}
return undefined;
}
set(key, value) {
for(let i=0;i<this.arr.length;i++) {
if(this.arr[i].key === key) {
this.arr[i].value = value;
return;
}
}
this.arr.push({key, value})
}
values() {
return this.arr;
}
}
let m = new OrderedMap();
m.set('b', 60)
m.set('a', 10)
m.set('c', 20)
m.set('d', 89)
console.log(m.get('a'));
console.log(m.values());
https://github.com/js-sdsl/js-sdsl
The OrderedMap in Js-sdsl maybe helpful.
This is a sorted-map which implement refer to C++ STL Map.
/*
* key value
* 1 1
* 2 2
* 3 3
* Sorted by key.
*/
const mp = new OrderedMap(
[1, 2, 3].map((element, index) => [index, element])
);
mp.setElement(1, 2); // O(logn)
mp.eraseElementByKey(1) // O(logn)
// custom comparison function
mp = new OrderedMap(
[1, 2, 3].map((element, index) => [index, element]),
(x, y) => x - y
);
// enable tree iterator index (enableIndex = true)
console.log(new OrderedMap([[0, 1], [1, 1]], undefined, true).begin(),next().index); // 1

Find duplicate object values in an array and merge them - JAVASCRIPT

I have an array of objects which contain certain duplicate properties: Following is the array sample:
var jsonData = [{x:12, machine1: 7}, {x:15, machine2:7},{x:12, machine2: 8}];
So what i need is to merge the objects with same values of x like the following array:
var jsonData = [{x:12, machine1:7, machine2:8}, {x:15, machine2:7}]
I like the lodash library.
https://lodash.com/docs#groupBy
_.groupBy(jsonData, 'x') produces:
12: [ {x=12, machine1=7}, {x=12, machine2=8} ],
15: [ {x=15, machine2=7} ]
your desired result is achieved like this:
var jsonData = [{x:12, machine1: 7}, {x:15, machine2:7},{x:12, machine2: 8}];
var groupedByX = _.groupBy(jsonData, 'x');
var result = [];
_.forEach(groupedByX, function(value, key){
var obj = {};
for(var i=0; i<value.length; i++) {
_.defaults(obj, value[i]);
}
result.push(obj);
});
I'm not sure if you're looking for pure JavaScript, but if you are, here's one solution. It's a bit heavy on nesting, but it gets the job done.
// Loop through all objects in the array
for (var i = 0; i < jsonData.length; i++) {
// Loop through all of the objects beyond i
// Don't increment automatically; we will do this later
for (var j = i+1; j < jsonData.length; ) {
// Check if our x values are a match
if (jsonData[i].x == jsonData[j].x) {
// Loop through all of the keys in our matching object
for (var key in jsonData[j]) {
// Ensure the key actually belongs to the object
// This is to avoid any prototype inheritance problems
if (jsonData[j].hasOwnProperty(key)) {
// Copy over the values to the first object
// Note this will overwrite any values if the key already exists!
jsonData[i][key] = jsonData[j][key];
}
}
// After copying the matching object, delete it from the array
// By deleting this object, the "next" object in the array moves back one
// Therefore it will be what j is prior to being incremented
// This is why we don't automatically increment
jsonData.splice(j, 1);
} else {
// If there's no match, increment to the next object to check
j++;
}
}
}
Note there is no defensive code in this sample; you probably want to add a few checks to make sure the data you have is formatted correctly before passing it along.
Also keep in mind that you might have to decide how to handle instances where two keys overlap but do not match (e.g. two objects both having machine1, but one with the value of 5 and the other with the value of 9). As is, whatever object comes later in the array will take precedence.
const mergeUnique = (list, $M = new Map(), id) => {
list.map(e => $M.has(e[id]) ? $M.set(e[id], { ...e, ...$M.get(e[id]) }) : $M.set(e[id], e));
return Array.from($M.values());
};
id would be x in your case
i created a jsperf with email as identifier: https://jsperf.com/mergeobjectswithmap/
it's a lot faster :)

How to convert array into object?

I have this array, var arr = [0, 1, 2]
and I would like to convert it into an object like this,
Object{
data: [0, 1, 2]
}
How would I get the desired output using a function perhaps? Thanks.
Just create an object and assign the array to one it it's properties:
var arr = [0, 1, 2];
var obj = {
data : arr
};
Or if you have an existing object, you can add the array by name:
obj['data'] = arr;
Or dot notation:
obj.data = arr;
You should be aware that these are all copying the array by reference, so any updates you make to the arr variable will update obj.data as well. If you want to copy by value, you could do something like:
var obj = {
data: arr.slice(0)
};
See this JSFiddle for an example of copying by reference versus copying by value. You could read the answer to this question for more information about copying by value vs copying by reference.
You can do this very easily like this var obj = {data:arr}; However I think you should consider what purpose you are using the object for. An array is technically already a javascript object so you may not even need to do this
It's quite easy you just need a factory for it.
function arrayToObjectTransformationFactory($array, $transformationTransportProtocol){
return function($array){
if ( !Array.prototype.forEach ) {
Array.prototype.forEach = function(fn, scope) {
for(var i = 0, len = this.length; i < len; ++i) {
fn.call(scope, this[i], i, this);
}
};
}
$array.forEach($transformationTransportProtocol)
return { "data": $array };
}($array);
}
arrayToObjectTransformationFactory([0, 1, 2], function($element, $index, $array){
var quux = [];
quux.push($array[$index]);
});
Should work cross browser and with jQuery too.

jQuery function to get all unique elements from an array?

jQuery.unique lets you get unique elements of an array, but the docs say the function is mostly for internal use and only operates on DOM elements. Another SO response said the unique() function worked on numbers, but that this use case is not necessarily future proof because it's not explicitly stated in the docs.
Given this, is there a "standard" jQuery function for accessing only the unique values — specifically, primitives like integers — in an array? (Obviously, we can construct a loop with the each() function, but we are new to jQuery and would like to know if there is a dedicated jQuery function for this.)
You can use array.filter to return the first item of each distinct value-
var a = [ 1, 5, 1, 6, 4, 5, 2, 5, 4, 3, 1, 2, 6, 6, 3, 3, 2, 4 ];
var unique = a.filter(function(itm, i, a) {
return i == a.indexOf(itm);
});
console.log(unique);
If supporting IE8 and below is primary, don't use the unsupported filter method.
Otherwise,
if (!Array.prototype.filter) {
Array.prototype.filter = function(fun, scope) {
var T = this, A = [], i = 0, itm, L = T.length;
if (typeof fun == 'function') {
while(i < L) {
if (i in T) {
itm = T[i];
if (fun.call(scope, itm, i, T)) A[A.length] = itm;
}
++i;
}
}
return A;
}
}
Just use this code as the basis of a simple JQuery plugin.
$.extend({
distinct : function(anArray) {
var result = [];
$.each(anArray, function(i,v){
if ($.inArray(v, result) == -1) result.push(v);
});
return result;
}
});
Use as so:
$.distinct([0,1,2,2,3]);
Based on #kennebec's answer, but fixed for IE8 and below by using jQuery wrappers around the array to provide missing Array functions filter and indexOf:
$.makeArray() wrapper might not be absolutely needed, but you'll get odd results if you omit this wrapper and JSON.stringify the result otherwise.
var a = [1,5,1,6,4,5,2,5,4,3,1,2,6,6,3,3,2,4];
// note: jQuery's filter params are opposite of javascript's native implementation :(
var unique = $.makeArray($(a).filter(function(i,itm){
// note: 'index', not 'indexOf'
return i == $(a).index(itm);
}));
// unique: [1, 5, 6, 4, 2, 3]
I would use underscore.js, which provides a uniq method that does what you want.
// for numbers
a = [1,3,2,4,5,6,7,8, 1,1,4,5,6]
$.unique(a)
[7, 6, 1, 8, 3, 2, 5, 4]
// for string
a = ["a", "a", "b"]
$.unique(a)
["b", "a"]
And for dom elements there is no example is needed here I guess because you already know that!
Here is the jsfiddle link of live example:
http://jsfiddle.net/3BtMc/4/
Paul Irish has a "Duck Punching" method (see example 2) that modifies jQuery's $.unique() method to return unique elements of any type:
(function($){
var _old = $.unique;
$.unique = function(arr){
// do the default behavior only if we got an array of elements
if (!!arr[0].nodeType){
return _old.apply(this,arguments);
} else {
// reduce the array to contain no dupes via grep/inArray
return $.grep(arr,function(v,k){
return $.inArray(v,arr) === k;
});
}
};
})(jQuery);
Walk the array and push items into a hash as you come across them. Cross-reference the hash for each new element.
Note that this will ONLY work properly for primitives (strings, numbers, null, undefined, NaN) and a few objects that serialize to the same thing (functions, strings, dates, possibly arrays depending on content). Hashes in this will collide as they all serialize to the same thing, e.g. "[object Object]"
Array.prototype.distinct = function(){
var map = {}, out = [];
for(var i=0, l=this.length; i<l; i++){
if(map[this[i]]){ continue; }
out.push(this[i]);
map[this[i]] = 1;
}
return out;
}
There's also no reason you can't use jQuery.unique. The only thing I don't like about it is that it destroys the ordering of your array. Here's the exact code for it if you're interested:
Sizzle.uniqueSort = function(results){
if ( sortOrder ) {
hasDuplicate = baseHasDuplicate;
results.sort(sortOrder);
if ( hasDuplicate ) {
for ( var i = 1; i < results.length; i++ ) {
if ( results[i] === results[i-1] ) {
results.splice(i--, 1);
}
}
}
}
return results;
};
this is js1568's solution, modified to work on a generic array of objects, like:
var genericObject=[
{genProp:'this is a string',randomInt:10,isBoolean:false},
{genProp:'this is another string',randomInt:20,isBoolean:false},
{genProp:'this is a string',randomInt:10,isBoolean:true},
{genProp:'this is another string',randomInt:30,isBoolean:false},
{genProp:'this is a string',randomInt:40,isBoolean:true},
{genProp:'i like strings',randomInt:60,isBoolean:true},
{genProp:'this is a string',randomInt:70,isBoolean:true},
{genProp:'this string is unique',randomInt:50,isBoolean:true},
{genProp:'this is a string',randomInt:50,isBoolean:false},
{genProp:'i like strings',randomInt:70,isBoolean:false}
]
It accepts one more parameter called propertyName, guess! :)
$.extend({
distinctObj:function(obj,propertyName) {
var result = [];
$.each(obj,function(i,v){
var prop=eval("v."+propertyName);
if ($.inArray(prop, result) == -1) result.push(prop);
});
return result;
}
});
so, if you need to extract a list of unique values for a given property, for example the values used for randomInt property, use this:
$.distinctObj(genericObject,'genProp');
it returns an array like this:
["this is a string", "this is another string", "i like strings", "this string is unique"]
function array_unique(array) {
var unique = [];
for ( var i = 0 ; i < array.length ; ++i ) {
if ( unique.indexOf(array[i]) == -1 )
unique.push(array[i]);
}
return unique;
}
Plain JavaScript modern solution if you don't need IE support (Array.from is not supported in IE).
You can use combination of Set and Array.from.
const arr = [1, 1, 11, 2, 4, 2, 5, 3, 1];
const set = new Set(arr);
const uniqueArr = Array.from(set);
console.log(uniqueArr);
The Set object lets you store unique values of any type, whether primitive values or object references.
The Array.from() method creates a new Array instance from an array-like or iterable object.
Also Array.from() can be replaced with spread operator.
const arr = [1, 1, 11, 2, 4, 2, 5, 3, 1];
const set = new Set(arr);
const uniqueArr = [...set];
console.log(uniqueArr);
You can use a jQuery plugin called Array Utilities to get an array of unique items.
It can be done like this:
var distinctArray = $.distinct([1, 2, 2, 3])
distinctArray = [1,2,3]
If anyone is using knockoutjs try:
ko.utils.arrayGetDistinctValues()
BTW have look at all ko.utils.array* utilities.
As of jquery 3.0 you can use $.uniqueSort(ARRAY)
Example
array = ["1","2","1","2"]
$.uniqueSort(array)
=> ["1", "2"]
If you need to support IE 8 or earlier, you can use jQuery to accomplish this.
var a = [1,2,2,3,4,3,5];
var unique = $.grep(a, function (item, index) {
return index === $.inArray(item, a);
});

Categories