How to get unique values in an array [duplicate] - javascript

This question already has answers here:
Get all unique values in a JavaScript array (remove duplicates)
(91 answers)
Closed 1 year ago.
How can I get a list of unique values in an array? Do I always have to use a second array or is there something similar to java's hashmap in JavaScript?
I am going to be using JavaScript and jQuery only. No additional libraries can be used.

Here's a much cleaner solution for ES6 that I see isn't included here. It uses the Set and the spread operator: ...
var a = [1, 1, 2];
[... new Set(a)]
Which returns [1, 2]

Or for those looking for a one-liner (simple and functional) compatible with current browsers:
let a = ["1", "1", "2", "3", "3", "1"];
let unique = a.filter((item, i, ar) => ar.indexOf(item) === i);
console.log(unique);
Update 2021
I would recommend checking out Charles Clayton's answer, as of recent changes to JS there are even more concise ways to do this.
Update 18-04-2017
It appears as though 'Array.prototype.includes' now has widespread support in the latest versions of the mainline browsers (compatibility)
Update 29-07-2015:
There are plans in the works for browsers to support a standardized 'Array.prototype.includes' method, which although does not directly answer this question; is often related.
Usage:
["1", "1", "2", "3", "3", "1"].includes("2"); // true
Pollyfill (browser support, source from mozilla):
// https://tc39.github.io/ecma262/#sec-array.prototype.includes
if (!Array.prototype.includes) {
Object.defineProperty(Array.prototype, 'includes', {
value: function(searchElement, fromIndex) {
// 1. Let O be ? ToObject(this value).
if (this == null) {
throw new TypeError('"this" is null or not defined');
}
var o = Object(this);
// 2. Let len be ? ToLength(? Get(O, "length")).
var len = o.length >>> 0;
// 3. If len is 0, return false.
if (len === 0) {
return false;
}
// 4. Let n be ? ToInteger(fromIndex).
// (If fromIndex is undefined, this step produces the value 0.)
var n = fromIndex | 0;
// 5. If n ≥ 0, then
// a. Let k be n.
// 6. Else n < 0,
// a. Let k be len + n.
// b. If k < 0, let k be 0.
var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
// 7. Repeat, while k < len
while (k < len) {
// a. Let elementK be the result of ? Get(O, ! ToString(k)).
// b. If SameValueZero(searchElement, elementK) is true, return true.
// c. Increase k by 1.
// NOTE: === provides the correct "SameValueZero" comparison needed here.
if (o[k] === searchElement) {
return true;
}
k++;
}
// 8. Return false
return false;
}
});
}

Since I went on about it in the comments for #Rocket's answer, I may as well provide an example that uses no libraries. This requires two new prototype functions, contains and unique
Array.prototype.contains = function(v) {
for (var i = 0; i < this.length; i++) {
if (this[i] === v) return true;
}
return false;
};
Array.prototype.unique = function() {
var arr = [];
for (var i = 0; i < this.length; i++) {
if (!arr.contains(this[i])) {
arr.push(this[i]);
}
}
return arr;
}
var duplicates = [1, 3, 4, 2, 1, 2, 3, 8];
var uniques = duplicates.unique(); // result = [1,3,4,2,8]
console.log(uniques);
For more reliability, you can replace contains with MDN's indexOf shim and check if each element's indexOf is equal to -1: documentation

One Liner, Pure JavaScript
With ES6 syntax
list = list.filter((x, i, a) => a.indexOf(x) === i)
x --> item in array
i --> index of item
a --> array reference, (in this case "list")
With ES5 syntax
list = list.filter(function (x, i, a) {
return a.indexOf(x) === i;
});
Browser Compatibility: IE9+

Using EcmaScript 2016 you can simply do it like this.
var arr = ["a", "a", "b"];
var uniqueArray = Array.from(new Set(arr)); // Unique Array ['a', 'b'];
Sets are always unique, and using Array.from() you can convert a Set to an array. For reference have a look at the documentations.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set

These days, you can use ES6's Set data type to convert your array to a unique Set. Then, if you need to use array methods, you can turn it back into an Array:
var arr = ["a", "a", "b"];
var uniqueSet = new Set(arr); // {"a", "b"}
var uniqueArr = Array.from(uniqueSet); // ["a", "b"]
//Then continue to use array methods:
uniqueArr.join(", "); // "a, b"

If you want to leave the original array intact,
you need a second array to contain the uniqe elements of the first-
Most browsers have Array.prototype.filter:
const unique = array1.filter((item, index, array) => array.indexOf(item) === index);
//if you need a 'shim':
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;
}
Array.prototype.indexOf= Array.prototype.indexOf || function(what, i){
if(!i || typeof i!= 'number') i= 0;
var L= this.length;
while(i<L){
if(this[i]=== what) return i;
++i;
}
return -1;
}

Fast, compact, no nested loops, works with any object not just strings and numbers, takes a predicate, and only 5 lines of code!!
function findUnique(arr, predicate) {
var found = {};
arr.forEach(d => {
found[predicate(d)] = d;
});
return Object.keys(found).map(key => found[key]);
}
Example: To find unique items by type:
var things = [
{ name: 'charm', type: 'quark'},
{ name: 'strange', type: 'quark'},
{ name: 'proton', type: 'boson'},
];
var result = findUnique(things, d => d.type);
// [
// { name: 'charm', type: 'quark'},
// { name: 'proton', type: 'boson'}
// ]
If you want it to find the first unique item instead of the last add a found.hasOwnPropery() check in there.

Not native in Javascript, but plenty of libraries have this method.
Underscore.js's _.uniq(array) (link) works quite well (source).

If you don't need to worry so much about older browsers, this is exactly what Sets are designed for.
The Set object lets you store unique values of any type, whether
primitive values or object references.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
const set1 = new Set([1, 2, 3, 4, 5, 1]);
// returns Set(5) {1, 2, 3, 4, 5}

Using jQuery, here's an Array unique function I made:
Array.prototype.unique = function () {
var arr = this;
return $.grep(arr, function (v, i) {
return $.inArray(v, arr) === i;
});
}
console.log([1,2,3,1,2,3].unique()); // [1,2,3]

Short and sweet solution using second array;
var axes2=[1,4,5,2,3,1,2,3,4,5,1,3,4];
var distinct_axes2=[];
for(var i=0;i<axes2.length;i++)
{
var str=axes2[i];
if(distinct_axes2.indexOf(str)==-1)
{
distinct_axes2.push(str);
}
}
console.log("distinct_axes2 : "+distinct_axes2); // distinct_axes2 : 1,4,5,2,3

Majority of the solutions above have a high run time complexity.
Here is the solution that uses reduce and can do the job in O(n) time.
Array.prototype.unique = Array.prototype.unique || function() {
var arr = [];
this.reduce(function (hash, num) {
if(typeof hash[num] === 'undefined') {
hash[num] = 1;
arr.push(num);
}
return hash;
}, {});
return arr;
}
var myArr = [3,1,2,3,3,3];
console.log(myArr.unique()); //[3,1,2];
Note:
This solution is not dependent on reduce. The idea is to create an object map and push unique ones into the array.

You only need vanilla JS to find uniques with Array.some and Array.reduce. With ES2015 syntax it's only 62 characters.
a.reduce((c, v) => b.some(w => w === v) ? c : c.concat(v)), b)
Array.some and Array.reduce are supported in IE9+ and other browsers. Just change the fat arrow functions for regular functions to support in browsers that don't support ES2015 syntax.
var a = [1,2,3];
var b = [4,5,6];
// .reduce can return a subset or superset
var uniques = a.reduce(function(c, v){
// .some stops on the first time the function returns true
return (b.some(function(w){ return w === v; }) ?
// if there's a match, return the array "c"
c :
// if there's no match, then add to the end and return the entire array
c.concat(v)}),
// the second param in .reduce is the starting variable. This is will be "c" the first time it runs.
b);
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

Another thought of this question. Here is what I did to achieve this with fewer code.
var distinctMap = {};
var testArray = ['John', 'John', 'Jason', 'Jason'];
for (var i = 0; i < testArray.length; i++) {
var value = testArray[i];
distinctMap[value] = '';
};
var unique_values = Object.keys(distinctMap);
console.log(unique_values);

Array.prototype.unique = function () {
var dictionary = {};
var uniqueValues = [];
for (var i = 0; i < this.length; i++) {
if (dictionary[this[i]] == undefined){
dictionary[this[i]] = i;
uniqueValues.push(this[i]);
}
}
return uniqueValues;
}

I have tried this problem in pure JS.
I have followed following steps 1. Sort the given array, 2. loop through the sorted array, 3. Verify previous value and next value with current value
// JS
var inpArr = [1, 5, 5, 4, 3, 3, 2, 2, 2,2, 100, 100, -1];
//sort the given array
inpArr.sort(function(a, b){
return a-b;
});
var finalArr = [];
//loop through the inpArr
for(var i=0; i<inpArr.length; i++){
//check previous and next value
if(inpArr[i-1]!=inpArr[i] && inpArr[i] != inpArr[i+1]){
finalArr.push(inpArr[i]);
}
}
console.log(finalArr);
Demo

You can enter array with duplicates and below method will return array with unique elements.
function getUniqueArray(array){
var uniqueArray = [];
if (array.length > 0) {
uniqueArray[0] = array[0];
}
for(var i = 0; i < array.length; i++){
var isExist = false;
for(var j = 0; j < uniqueArray.length; j++){
if(array[i] == uniqueArray[j]){
isExist = true;
break;
}
else{
isExist = false;
}
}
if(isExist == false){
uniqueArray[uniqueArray.length] = array[i];
}
}
return uniqueArray;
}

Here is an approach with customizable equals function which can be used for primitives as well as for custom objects:
Array.prototype.pushUnique = function(element, equalsPredicate = (l, r) => l == r) {
let res = !this.find(item => equalsPredicate(item, element))
if(res){
this.push(element)
}
return res
}
usage:
//with custom equals for objects
myArrayWithObjects.pushUnique(myObject, (left, right) => left.id == right.id)
//with default equals for primitives
myArrayWithPrimitives.pushUnique(somePrimitive)

I was just thinking if we can use linear search to eliminate the duplicates:
JavaScript:
function getUniqueRadios() {
var x=document.getElementById("QnA");
var ansArray = new Array();
var prev;
for (var i=0;i<x.length;i++)
{
// Check for unique radio button group
if (x.elements[i].type == "radio")
{
// For the first element prev will be null, hence push it into array and set the prev var.
if (prev == null)
{
prev = x.elements[i].name;
ansArray.push(x.elements[i].name);
} else {
// We will only push the next radio element if its not identical to previous.
if (prev != x.elements[i].name)
{
prev = x.elements[i].name;
ansArray.push(x.elements[i].name);
}
}
}
}
alert(ansArray);
}
HTML:
<body>
<form name="QnA" action="" method='post' ">
<input type="radio" name="g1" value="ANSTYPE1"> good </input>
<input type="radio" name="g1" value="ANSTYPE2"> avg </input>
<input type="radio" name="g2" value="ANSTYPE3"> Type1 </input>
<input type="radio" name="g2" value="ANSTYPE2"> Type2 </input>
<input type="submit" value='SUBMIT' onClick="javascript:getUniqueRadios()"></input>
</form>
</body>

Related

Remove Strings, Keep Numbers In Array With JavaScript

Other articles talk about removing strings from an array based on a search term.
But I'm trying to indentify which elements are strings and which elements are numbers in an array, and then remove all strings to return a new array.
function filter_list(l) {
let newArray = [];
for (let i = 0; i < l.length; i ++) {
if (i !== "^[a-zA-Z0-9_.-]*$") {
newArray = newArray + i;
}
}
return newArray;
}
This is returning 0123.
Why is it not returning an array?
Why is if (i !== "^[a-zA-Z0-9_.-]*$") not working? How else can I check for when an element is a string (something in quotes) within the array?
https://www.codewars.com/kata/list-filtering/train/javascript
Thanks
You can is typeof keyword. and filter(). I have tested the code its passing all tests in codewars.
Using ES6 Arrow Function
function filter_list(l) {
return l.filter(x => typeof x === "number");
}
console.log(filter_list([1,2,'a','b']))
Without Arrow Function
function filter_list(l) {
return l.filter(function(x){
return typeof x === "number"
});
}
console.log(filter_list([1,2,'a','b']))
Using Simple Loops
function filter_list(l) {
let newArr = [];
for(let i = 0;i<l.length;i++){
if(typeof l[i] === "number") newArr.push(l[i]);
}
return newArr
}
console.log(filter_list([1,2,'a','b']))
Regex is not good way to parse such table. Try isNaN
console.log(
[1,2,3,4,5, 'a', 'b', 1, 3].filter(item => !isNaN(item) ? item : '')
)
If you want less hacky way try
function filter_list(l) {
// l is very bad name, because look similar to i
let newArray = [];
for (let i = 0; i < l.length; i ++) {
!isNaN(l[i]) ? newArray.push(l[i]) : ''
}
return newArray;
}
or even
for (let i = 0; i < l.length; i ++) {
!isNaN(l[i]) ? newArray[i] = l[i] : ''
}
Hovewer, this task can be done with regexes, but I cannot recommend this solution.
[1,2,3,4,5, 'a', 'b', 1, 3].join(' ').replace(/\D/gm, '').split('')
var numberArray: any[];
numberArray.filter(Number)
Using this you can filter only numbers in an array and then can performe what you want.
function filter_list(l) {
return l.filter(x => typeof x === "number");
}
console.log(filter_list([1,2,'a','b']))
I worked out a simple answer that will work as well using the same logic required to solve your problem. I used it on an example where you have an array of temperature values, and you want to remove all the values which are strings from the existing array, then populate the new empty array.You can use typeof operator to identify the type of value in the temperatures array at position i which is the index of that array element. If the type of that value is not a string then push the value of the temperatures array at the current index position to the new array.
const temperatures = [3, -2, -6, -1, 'error', 9, 13, 17, 15, 14, 9, 5];
const cleanTemperatures = [];
for (let i = 0; i < temperatures.length; i++) {
if (typeof temperatures[i] !== 'string') {
cleanTemperatures.push(temperatures[i]);
}
}

return object if list<object> value is exists (Javascript, jquery grep/map)

I'm using grep and map functions to get the object if the value is exists in the list, but it does not work well.
I have a list customList and the customObject has the int id property and List value properties.
customobject[0].id
customObject[0].value[]
What I want is check if in the List the value 5 exists.
The function what I'm using is:
var gettedcustomObject = $.grep(customList, function (e) {
var result = e.Value.map(function (a) { return a === 5;});
return result;
});
What am I doing wrong and what is the correct implementation?
Note: 2x foreach could be a solution, but customList has more than 1000 objects with 10000 values. I think that slow down the proces.
This should do it.
var gettedcustomObject = customList.filter(function(v){
var ln = v.Value.length;
for(var i = 0; i < ln; i++){
if(v.Value[i] == 5){
return true;
}
}
return false;
// Or simply:
// return v.Value.indexOf(5) != -1;
});
This will work if v.Value is an array.
You should look at some: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some#Polyfill
Way faster than the other methods like filter, map or sort as it was designed for this.
//List to work against
var arr = [];
//Populate
while (arr.length < 9999999) {
arr.push(Math.random() * 999999)
}
//Set element to find
arr[10] = "test";
//Begin timing
var d = new Date().getTime();
//Run filter
console.log(arr.filter(function(a){return a === "test"}).length > 0);
//How long did it take
console.log("`filter` took:",new Date().getTime() - d,"ms")
//Begin timing
d = new Date().getTime();
//Run filter
console.log(arr.some(function(a){return a === "test"}));
//How long did it take
console.log("`some` took:",new Date().getTime() - d,"ms")
<script>
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some#Polyfill
// Production steps of ECMA-262, Edition 5, 15.4.4.17
// Reference: http://es5.github.io/#x15.4.4.17
if (!Array.prototype.some) {
Array.prototype.some = function(fun/*, thisArg*/) {
'use strict';
if (this == null) {
throw new TypeError('Array.prototype.some called on null or undefined');
}
if (typeof fun !== 'function') {
throw new TypeError();
}
var t = Object(this);
var len = t.length >>> 0;
var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
for (var i = 0; i < len; i++) {
if (i in t && fun.call(thisArg, t[i], i, t)) {
return true;
}
}
return false;
};
}
</script>
If your goal is to find the first object in the list that contains 5 in the Value property, then you're looking for Array#find and Array#indexOf:
var gettedcustomObject = customList.find(function(entry) {
return entry.Value.indexOf(5) != -1;
});
Note that Array#find was added relatively recently and so you may need a polyfill for it (which is trivial). MDN has one.
Or you could use Array#includes instead of indexOf, which will be in ES2017 and is also polyfillable:
var gettedcustomObject = customList.find(function(entry) {
return entry.Value.includes(5);
});
Live Example (using indexOf):
var customList = [
{
note: "I'm not a match",
Value: [2, 3, 4]
},
{
note: "I'm not a match either",
Value: [78, 4, 27]
},
{
note: "I'm a match",
Value: [889, 5, 27]
},
{
note: "I'm also a match, but you won't find me",
Value: [4, 6, 5]
}
];
var gettedcustomObject = customList.find(function(entry) {
return entry.Value.indexOf(5) != -1;
});
console.log(gettedcustomObject);
If your logic matching the item inside Value were more complicated, you'd use Array#some and a callback function rathe than indexOf. But when looking to see if an array for an entry in an array based on ===, indexOf or the new Array#includes are the way to go.
one approach using Array.some() and Array.indexOf(). some loop break once the element is found
var gettedcustomObject;
customobject.some(function(obj){
if(obj.value.indexOf(5) >-1){
gettedcustomObject = obj;
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

Combaining two array into single multi dimensional array in javascript

status_name=Array("a","b","c","b","e","f");
status_id=Array( 1, 2, 3, 4, 5, 6);
How to combine these two arrays and to built multi dimensional array Expected Multidimensional array be like this
[["a", 1],["b", 2],["c", 3],["d", 4],["e", 5],["f", 6]]
Help me how to use above two array values and built my expected multidimensional array
Since you're including jQuery, you can use jQuery.map in a similar fashion to Linus' answer:
var result = [],
status_name = ["a","b","c","b","e","f"],
status_id = [1, 2, 3, 4, 5, 6];
result = $.map(status_name, function (el, idx) {
return [[el, status_id[idx]]];
});
Looking at your variable names, I'd guess that your coming from a language (like PHP). If that's the case, make sure you remember to declare local variables with the var keyword, otherwise you'll be polluting the global scope and you'll run into some hideous bugs in IE.
JavaScript has no buitin method for this, but you can easily write it yourself:
function zip(arrayA, arrayB) {
var length = Math.min(arrayA.length, arrayB.length);
var result = [];
for (var n = 0; n < length; n++) {
result.push([arrayA[n], arrayB[n]]);
}
return result;
}
The name zip is chosen because a function that does something like this is often called zip in other languages.
I tried Myself and brought this solution, It might help some one
status_name=Array("a","b","c","b","e","f");
status_id=Array( 1, 2, 3, 4, 5, 6);
Script:
Values=[];
for (i = 0; i < status_name.length; ++i)
{
Values[i] =Array(status_name[i], status_id[i]);
}
Using jQuery.map
var status_name = ["a","b","c","b","e","f"],
status_id = [1,2,3,4,5,6],
r = [];
r = $.map(status_name, function(n, i) {
return [[n, status_id[i]]];
});
Note the difference between return [[n, status_id[i]]] and return [n, status_id[i]]. Using the former will result in a 2d array while using the latter will result in a 1d array.
var combined = [], length = Math.min(status_name.length, status_id.length);
for(var i = 0; i < length; i++) {
combined.push([status_name[i], status_id[i]]);
}
You could also use Array.prototype.map, but that's not supported in all browsers:
var combined = status_name.map(function(name, index) { return [name, status_id[index]] });
try
function array_combine (keys, values) {
// Creates an array by using the elements of the first parameter as keys and the elements of the second as the corresponding values
//
// version: 1102.614
// discuss at: http://phpjs.org/functions/array_combine
// + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// + improved by: Brett Zamir (http://brett-zamir.me)
// * example 1: array_combine([0,1,2], ['kevin','van','zonneveld']);
// * returns 1: {0: 'kevin', 1: 'van', 2: 'zonneveld'}
var new_array = {},
keycount = keys && keys.length,
i = 0;
// input sanitation
if (typeof keys !== 'object' || typeof values !== 'object' || // Only accept arrays or array-like objects
typeof keycount !== 'number' || typeof values.length !== 'number' || !keycount) { // Require arrays to have a count
return false;
}
// number of elements does not match
if (keycount != values.length) {
return false;
}
for (i = 0; i < keycount; i++) {
new_array[keys[i]] = values[i];
}
return new_array;
Reference
- arr combine
- array combine

Getting a union of two arrays in JavaScript [duplicate]

This question already has answers here:
How to merge two arrays in JavaScript and de-duplicate items
(89 answers)
Closed 4 years ago.
Say I have an array of [34, 35, 45, 48, 49] and another array of [48, 55]. How can I get a resulting array of [34, 35, 45, 48, 49, 55]?
With the arrival of ES6 with sets and splat operator (at the time of being works only in Firefox, check compatibility table), you can write the following cryptic one liner:
var a = [34, 35, 45, 48, 49];
var b = [48, 55];
var union = [...new Set([...a, ...b])];
console.log(union);
Little explanation about this line: [...a, ...b] concatenates two arrays, you can use a.concat(b) as well. new Set() create a set out of it and thus your union. And the last [...x] converts it back to an array.
If you don't need to keep the order, and consider 45 and "45" to be the same:
function union_arrays (x, y) {
var obj = {};
for (var i = x.length-1; i >= 0; -- i)
obj[x[i]] = x[i];
for (var i = y.length-1; i >= 0; -- i)
obj[y[i]] = y[i];
var res = []
for (var k in obj) {
if (obj.hasOwnProperty(k)) // <-- optional
res.push(obj[k]);
}
return res;
}
console.log(union_arrays([34,35,45,48,49], [44,55]));
If you use the library underscore you can write like this
var unionArr = _.union([34,35,45,48,49], [48,55]);
console.log(unionArr);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js"></script>
Ref: http://underscorejs.org/#union
I'm probably wasting time on a dead thread here. I just had to implement this and went looking to see if I was wasting my time.
I really like KennyTM's answer. That's just how I would attack the problem. Merge the keys into a hash to naturally eliminate duplicates and then extract the keys. If you actually have jQuery you can leverage its goodies to make this a 2 line problem and then roll it into an extension. The each() in jQuery will take care of not iterating over items where hasOwnProperty() is false.
jQuery.fn.extend({
union: function(array1, array2) {
var hash = {}, union = [];
$.each($.merge($.merge([], array1), array2), function (index, value) { hash[value] = value; });
$.each(hash, function (key, value) { union.push(key); } );
return union;
}
});
Note that both of the original arrays are left intact. Then you call it like this:
var union = $.union(array1, array2);
If you wants to concatenate two arrays without any duplicate value,Just try this
var a=[34, 35, 45, 48, 49];
var b=[48, 55];
var c=a.concat(b).sort();
var res=c.filter((value,pos) => {return c.indexOf(value) == pos;} );
function unique(arrayName)
{
var newArray=new Array();
label: for(var i=0; i<arrayName.length;i++ )
{
for(var j=0; j<newArray.length;j++ )
{
if(newArray[j]==arrayName[i])
continue label;
}
newArray[newArray.length] = arrayName[i];
}
return newArray;
}
var arr1 = new Array(0,2,4,4,4,4,4,5,5,6,6,6,7,7,8,9,5,1,2,3,0);
var arr2= new Array(3,5,8,1,2,32,1,2,1,2,4,7,8,9,1,2,1,2,3,4,5);
var union = unique(arr1.concat(arr2));
console.log(union);
Adapted from: https://stackoverflow.com/a/4026828/1830259
Array.prototype.union = function(a)
{
var r = this.slice(0);
a.forEach(function(i) { if (r.indexOf(i) < 0) r.push(i); });
return r;
};
Array.prototype.diff = function(a)
{
return this.filter(function(i) {return a.indexOf(i) < 0;});
};
var s1 = [1, 2, 3, 4];
var s2 = [3, 4, 5, 6];
console.log("s1: " + s1);
console.log("s2: " + s2);
console.log("s1.union(s2): " + s1.union(s2));
console.log("s2.union(s1): " + s2.union(s1));
console.log("s1.diff(s2): " + s1.diff(s2));
console.log("s2.diff(s1): " + s2.diff(s1));
// Output:
// s1: 1,2,3,4
// s2: 3,4,5,6
// s1.union(s2): 1,2,3,4,5,6
// s2.union(s1): 3,4,5,6,1,2
// s1.diff(s2): 1,2
// s2.diff(s1): 5,6
I like Peter Ajtai's concat-then-unique solution, but the code's not very clear. Here's a nicer alternative:
function unique(x) {
return x.filter(function(elem, index) { return x.indexOf(elem) === index; });
};
function union(x, y) {
return unique(x.concat(y));
};
Since indexOf returns the index of the first occurence, we check this against the current element's index (the second parameter to the filter predicate).
Shorter version of kennytm's answer:
function unionArrays(a, b) {
const cache = {};
a.forEach(item => cache[item] = item);
b.forEach(item => cache[item] = item);
return Object.keys(cache).map(key => cache[key]);
};
You can use a jQuery plugin: jQuery Array Utilities
For example the code below
$.union([1, 2, 2, 3], [2, 3, 4, 5, 5])
will return [1,2,3,4,5]
function unite(arr1, arr2, arr3) {
newArr=arr1.concat(arr2).concat(arr3);
a=newArr.filter(function(value){
return !arr1.some(function(value2){
return value == value2;
});
});
console.log(arr1.concat(a));
}//This is for Sorted union following the order :)
function unionArrays() {
var args = arguments,
l = args.length,
obj = {},
res = [],
i, j, k;
while (l--) {
k = args[l];
i = k.length;
while (i--) {
j = k[i];
if (!obj[j]) {
obj[j] = 1;
res.push(j);
}
}
}
return res;
}
var unionArr = unionArrays([34, 35, 45, 48, 49], [44, 55]);
console.log(unionArr);
Somewhat similar in approach to alejandro's method, but a little shorter and should work with any number of arrays.
function unionArray(arrayA, arrayB) {
var obj = {},
i = arrayA.length,
j = arrayB.length,
newArray = [];
while (i--) {
if (!(arrayA[i] in obj)) {
obj[arrayA[i]] = true;
newArray.push(arrayA[i]);
}
}
while (j--) {
if (!(arrayB[j] in obj)) {
obj[arrayB[j]] = true;
newArray.push(arrayB[j]);
}
}
return newArray;
}
var unionArr = unionArray([34, 35, 45, 48, 49], [44, 55]);
console.log(unionArr);
Faster
http://jsperf.com/union-array-faster
I would first concatenate the arrays, then I would return only the unique value.
You have to create your own function to return unique values. Since it is a useful function, you might as well add it in as a functionality of the Array.
In your case with arrays array1 and array2 it would look like this:
array1.concat(array2) - concatenate the two arrays
array1.concat(array2).unique() - return only the unique values. Here unique() is a method you added to the prototype for Array.
The whole thing would look like this:
Array.prototype.unique = function () {
var r = new Array();
o: for(var i = 0, n = this.length; i < n; i++)
{
for(var x = 0, y = r.length; x < y; x++)
{
if(r[x]==this[i])
{
continue o;
}
}
r[r.length] = this[i];
}
return r;
}
var array1 = [34,35,45,48,49];
var array2 = [34,35,45,48,49,55];
// concatenate the arrays then return only the unique values
console.log(array1.concat(array2).unique());
Just wrote before for the same reason (works with any amount of arrays):
/**
* Returns with the union of the given arrays.
*
* #param Any amount of arrays to be united.
* #returns {array} The union array.
*/
function uniteArrays()
{
var union = [];
for (var argumentIndex = 0; argumentIndex < arguments.length; argumentIndex++)
{
eachArgument = arguments[argumentIndex];
if (typeof eachArgument !== 'array')
{
eachArray = eachArgument;
for (var index = 0; index < eachArray.length; index++)
{
eachValue = eachArray[index];
if (arrayHasValue(union, eachValue) == false)
union.push(eachValue);
}
}
}
return union;
}
function arrayHasValue(array, value)
{ return array.indexOf(value) != -1; }
Simple way to deal with merging single array values.
var values[0] = {"id":1235,"name":"value 1"}
values[1] = {"id":4323,"name":"value 2"}
var object=null;
var first=values[0];
for (var i in values)
if(i>0)
object= $.merge(values[i],first)
You can try these:
function union(a, b) {
return a.concat(b).reduce(function(prev, cur) {
if (prev.indexOf(cur) === -1) prev.push(cur);
return prev;
}, []);
}
or
function union(a, b) {
return a.concat(b.filter(function(el) {
return a.indexOf(el) === -1;
}));
}
ES2015 version
Array.prototype.diff = function(a) {return this.filter(i => a.indexOf(i) < 0)};
Array.prototype.union = function(a) {return [...this.diff(a), ...a]}
If you want a custom equals function to match your elements, you can use this function in ES2015:
function unionEquals(left, right, equals){
return left.concat(right).reduce( (acc,element) => {
return acc.some(elt => equals(elt, element))? acc : acc.concat(element)
}, []);
}
It traverses the left+right array. Then for each element, will fill the accumulator if it does not find that element in the accumulator. At the end, there are no duplicate as specified by the equals function.
Pretty, but probably not very efficient with thousands of objects.
I think it would be simplest to create a new array, adding the unique values only as determined by indexOf.
This seems to me to be the most straightforward solution, though I don't know if it is the most efficient. Collation is not preserved.
var a = [34, 35, 45, 48, 49],
b = [48, 55];
var c = union(a, b);
function union(a, b) { // will work for n >= 2 inputs
var newArray = [];
//cycle through input arrays
for (var i = 0, l = arguments.length; i < l; i++) {
//cycle through each input arrays elements
var array = arguments[i];
for (var ii = 0, ll = array.length; ii < ll; ii++) {
var val = array[ii];
//only add elements to the new array if they are unique
if (newArray.indexOf(val) < 0) newArray.push(val);
}
}
return newArray;
}
[i for( i of new Set(array1.concat(array2)))]
Let me break this into parts for you
// This is a list by comprehension
// Store each result in an element of the array
[i
// will be placed in the variable "i", for each element of...
for( i of
// ... the Set which is made of...
new Set(
// ...the concatenation of both arrays
array1.concat(array2)
)
)
]
In other words, it first concatenates both and then it removes the duplicates (a Set, by definition cannot have duplicates)
Do note, though, that the order of the elements is not guaranteed, in this case.

Categories

Resources