Getting key with the highest value from object - javascript

I have a object like that one:
Object {a: 1, b: 2, undefined: 1}
How can I quickly pull the largest value identifier (here: b) from it? I tried converting it to array and then sorting, but it didn't work out, since it got sorted alphabetically (and it seems like a overkill to juggle data back and forth just for getting one value out of three).

For example:
var obj = {a: 1, b: 2, undefined: 1};
Object.keys(obj).reduce(function(a, b){ return obj[a] > obj[b] ? a : b });
In ES6:
var obj = {a: 1, b: 2, undefined: 1};
Object.keys(obj).reduce((a, b) => obj[a] > obj[b] ? a : b);

Using Underscore or Lo-Dash:
var maxKey = _.max(Object.keys(obj), function (o) { return obj[o]; });
With ES6 Arrow Functions:
var maxKey = _.max(Object.keys(obj), o => obj[o]);
jsFiddle demo

Here is a suggestion in case you have many equal values and not only one maximum:
const getMax = object => {
return Object.keys(object).filter(x => {
return object[x] == Math.max.apply(null,
Object.values(object));
});
};
This returns an array, with the keys for all of them with the maximum value, in case there are some that have equal values.
For example: if
const obj = {apples: 1, bananas: 1, pears: 1 }
//This will return ['apples', 'bananas', 'pears']
If on the other hand there is a maximum:
const obj = {apples: 1, bananas: 2, pears: 1 }; //This will return ['bananas']
---> To get the string out of the array: ['bananas'][0] //returns 'bananas'`

Supposing you've an Object like this:
var obj = {a: 1, b: 2, undefined: 1}
You can do this
var max = Math.max.apply(null,Object.keys(obj).map(function(x){ return obj[x] }));
console.log(Object.keys(obj).filter(function(x){ return obj[x] == max; })[0]);

{a: 1, b: 2, undefined: 1}
The best work around I've seen is this
const chars = {a: 1, b: 2, undefined: 1}
//set maximum value to 0 and maxKey to an empty string
let max = 0;
let maxKey = "";
for(let char in chars){
if(chars[char]> max){
max = chars[char];
maxKey= char
}
}
console.log(maxKey)

Very basic method. might be slow to process
var v = {a: 1, b: 2, undefined: 1};
function geth(o){
var vals = [];
for(var i in o){
vals.push(o[i]);
}
var max = Math.max.apply(null, vals);
for(var i in o){
if(o[i] == max){
return i;
}
}
}
console.log(geth(v));

Combination of some ideas from other answers. This will get all the keys with the highest value, but using the spread operator to get the maximum value and then filter array method:
const getMax = object => {
let max = Math.max(...Object.values(object))
return Object.keys(object).filter(key => object[key]==max)
}
let obj = {a: 12, b: 11, c: 12};
getMax(obj)

let data = {a:1,b:2,undefined:3}
let maxValue = Object.entries(data).sort((x,y)=>y[1]-x[1])[0]
note: this is a very expensive process and would block the event loop if used with objects of large sizes(>=1000000). with large array slice the entries and call the above method recurrently using setTimeout.

If you need to return an array from an object with the keys for all duplicate properties with the (same or equal) highest value, try this:
const getMax = Object.keys(object)
.filter(x => {
return object[x] == Math.max.apply(null,
Object.values(object));
})
var object = { orange: 3, blue: 3, green: 1}
console.log(getMax) // ['orange', 'blue']

Related

Top highest values in an object (more if there are more max values and they are the same)

Lets suppose I have object like this:
var obj = {a : 5, b : 10, c : 15, d : 20, e : 20, f : 25};
I would like to get top 3 highest values - notice that d and e key have the same value and I need to get the keys also, so it would looks like:
Highest values:
f - 25
d - 20
e - 20
also if there are for example six values and four are identical:
var obj2 = {a:1, b:1, c:1, d:1, e:0,8, f: 0,5};
I need to show 4 highest.
Highest values:
a-1
b-1
c-1
d-1
I guess there is need to iterate over ALL object properties to get Math.max, but I also need a something to count 3 max numbers WITH their keys, and if there is more max (all the same) I need to "get them all!".
EDIT: there are great answers atm, so I guess I will not finish this code and just use given examples :)
This is an example implementation, with annotations to explain what is happening at each step.
function maxValues(o, n) {
// Get object values and sort descending
const values = Object.values(o).sort((a, b) => b - a);
// Check if more values exist than number required
if (values.length <= n) return o;
// Find nth maximum value
const maxN = values[n - 1];
// Filter object to return only key/value pairs where value >= maxN
return Object.entries(o)
.reduce((o, [k, v]) => v >= maxN ? { ...o, [k]: v } : o, {});
}
const a = maxValues({
a: 5,
b: 10,
c: 15,
d: 20,
e: 20,
f: 25
}, 3);
console.log(a);
const b = maxValues({
a: 1,
b: 1,
c: 1,
d: 1,
e: 0.8,
f: 0.5
}, 3);
console.log(b);
const c = maxValues({
a: 5,
b: 10,
}, 3);
console.log(c);
The callback passed to the Array.prototype.reduce function can be expanded out to the following:
return Object.entries(o)
.reduce(function (obj, [key, value]) {
if (v >= maxN) {
return Object.assign(obj, {
[key]: value
});
} else {
return obj;
}
}, {});
Instead, I condensed it down using an Arrow Function Expression, ternary operator, and spread syntax.
The ternary operator is essentially shorthand for an if/else statement. E.g.
condition ? true : false;
// or
v >= maxN ? { ...o, [k]: v } : o;
The spread syntax allows an iterable value to be expanded in place. In this instance, it's being used to copy existing key/value pairs from one object literal to another.
const a = { first_name: 'Rob', gender: 'male' };
const b = { ...a, username: 'fubar' };
console.log(b); // { first_name: 'Rob', gender: 'male', username: 'fubar' };
Simply,
Sort the object based on its values using, Object.entries
Get the least value you can filter.
Filter the entries and return as Object using Object.fromEntries.
function getTopValues(obj, topN)
{
var sortedEntries = Object.entries(obj).sort(function(a,b){return b[1]-a[1]});
var last = sortedEntries[topN-1][1];
var result = sortedEntries.filter(function(entry){
return entry[1] >= last;
});
console.log(Object.fromEntries(result));
}
getTopValues({a:5, b:10, c:15, d:20, e:20, f:25}, 3);
getTopValues({a:1, b:1, c:1, d:1, e:0.8, f: 0.5}, 3);
getTopValues({a:1, b:1, c:1, d:1, e:0.8, f: 0.5}, 5);
So, you want to find the top 3 highest and if there are multiple identical highest then you want to include all of that.
This problem is asked in a slightly weird fashion.
I am going to assume that if there is something like a:1 b:1 c:2 d:2 e:3,
you would like to include a,b,c and d.
First of all, you only have to keep track of the keys because you can get the values instantly at the end.
Ok! Let's start. (efficient but ugly)
class Numandamount {
constructor(number, amount) {
this.number = number;
this.amount = amount;
}
}
//That's just a class to link numbers and their amounts
var numtoamount = [];
//Now let's fill that array!
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
var num = obj.property;
var found = false;
for(Numandamount naa in numtoamount){
if(naa.number == num){
naa.amount++;
found = true;
}
}
if(!found){
naa.push(new Numandamount(num,1));
}
}
}
//The array is done!
numtoamount.sort(function(a,b){return b.number-a.number});
//Now all we have to do is loop through it!
var count = 0; // keep track of how many we did
var i = 0;
while(count<4 && i<numtoarray.length){
count += numtoamount[i].amount;
i++;
}
//BOOOM WE DID IT
// I is the biggest index so all we have to do is:
for(var j = 0;j<i;j++){
console.log("We have "+numtoamount[j].amount+" "+numtoamount[j].number+"'s");
}
For eg. it will print out for this example obj: {a:1 b:1 c:4 d:6 e:7 f:4}
We have 1 7's
We have 1 6's
We have 2 4's
If you would like some other implementation please comment below!
I put my heart into this <3
I would start with transforming your object into an array of objects:
const arr = []
for (var key in obj){
arr.push( {[key]: obj[key]} )
}
Now you have an array that looks like this:
[
{"f": 25},
{"d": 20},
{"e": 20},
{"c": 15},
{"b": 10},
{"a": 5}
]
Now you can sort your objects by the magnitude of their values:
const sortedArray = arr.sort( (a,b) => {
if (Object.values(a)[0] > Object.values(b)[0]) {
return -1
}
})
Which would give:
[
{"f": 25},
{"d": 20},
{"e": 20},
{"c": 15},
{"b": 10},
{"a": 5}
]
Then you can just pick however many values off the top you want. For example
sortedArray.filter( (item, index) => {
if (index <= 2 || Object.values(item)[0] === Object.values(sortedArray[0])[0]) {
return item
}
})
Which gives:
[
{"f": 25},
{"d": 20},
{"e": 20}
]
Or in the case of your second object, it would match the n highest values, but also grab any other values that are equal to the highest value.
As a single function:
function sortYourObject(object, number){
var arr = []
for (var key in object){
arr.push( {[key]: object[key]} )
}
const sortedArray = arr.sort( (a,b) => {
if (Object.values(a)[0] > Object.values(b)[0]) {
return -1
}
})
const endresult = sortedArray.filter( (item, index) => {
if (index <= 2 || Object.values(item)[0] === Object.values(sortedArray[0])[0]) {
return item
}
})
return endresult
}

Find keys of the 3 largest values in a Javascript Object with O(n) complexity?

Say you have an object such as:
let objToCheck = {
a: 2,
b: 5,
c: 9,
d: 33
};
How would you go about returning the keys of the three largest values in ascending order, which in this case would be: [ 'c', 'h', 'd' ], in linear time? Evidently you need to loop through the entire object once to compare all values, but I'm having troubling coming up with a solution that doesn't involve nested loops which I believe is O(nΒ²). Here is what my solution currently looks like so far:
function findBig3 (obj){
const res = [];
const largest = Object.values(obj).sort((a,b) => { return b-a }).slice(0,3);
for (let key in obj){
largest.forEach((val) => {
if (obj[key] === val) res.push(key);
}
});
}
return res;
}
I would imagine you need to declare three variables, such as big1, big2, big3, and as you loop through the object do some type of comparison check and reassign as appropriate, but I'm struggling with the implementation.
you can keep pushing 3 objects in an array and keep sorting the array, assuming number of elements you need k is sufficiently less than n, this can give linear efficiency on average.
let objToCheck = {
a: 2,
b: 5,
c: 9,
d: 33,
e: 4,
f: 8,
g: 3,
h: 10
};
function findBig3(obj){
var res = [-1,-1,-1];
for (let key in obj){
res[3] = obj[key];
res.sort(function(a,b){return b-a});
}
res.pop();
return res;
}
console.log(findBig3(objToCheck));
This algorithm runs in O(n).
function getThreeLargestKeys(obj){
var k1, k2, k3;
var v1, v2, v3;
v1 = v2 = v3 = -Infinity;
// O(1)
var insertKey = function(key){
var value = obj[key]; // note 1
// note 2
if(value >= v1){
v3 = v2; v2 = v1; v1 = value;
k3 = k2; k2 = k1; k1 = key;
}else if(value >= v2){
v3 = v2; v2 = value;
k3 = k2; k2 = key;
}else if(value >= v3){
v3 = value;
k3 = key;
}
};
// O(n)
for(var key in obj){
// note 3
insertKey(key);
}
return [k1, k2, k3];
}
https://jsfiddle.net/DerekL/pzatq729/
Please do not copy-paste the code right into your homework as your solution. Rewrite the code once you fully understand it.
Note:
This assumes that object lookup is O(1). This ultimately depends on how it is implemented in the interpreter, but it is usually lower than O(log n).
These conditionals can certainly be optimized. I will leave that as a practice for the reader.
Normally we should check if the key is owned by the object instance, but here I will assume that the input object is not inherited from Object.prototype.
If you just change Object.values to Object.keys and use the key to select from the original object, you can avoid the last loop.
let objToCheck = {
a: 2,
b: 5,
c: 9,
d: 33,
e: 4,
f: 8,
g: 3,
h: 10
};
function findBig3(obj){
return Object.keys(obj).sort((a,b) => {return obj[b]-obj[a]}).slice(0,3);
}
console.log(findBig3(objToCheck));

Return object with highest key/value pairs from an array of objects

Given an array of objects, I want to return an object with the highest values from all the objects.
let countObj = [{2:1},{2:4, 5:1},{3:3}]
let finalObj = {}
let primes = [2,3,5]
// finalObj should return {2:4, 3:3, 5:1}
I feel like there should be some way to use the primes array and reduce on the countObj to get the desired result.
primes.forEach(p => countObj.reduce((a,b) =>{
if (a[p]){ //if prime no. exists as key in a
a[p] > b[p] ? //keep key/val pair in a : replace key/val pair
}else{ //if new prime is not a key in a
a[p] = b[p]
}
},{})
I'm not sure if the logic is correct and also, I don't know how to get it to return the final object.
You could check if the stored value is greater than the actual value and if not, then assign the value to the result set.
var countObj = [{ 2: 1 }, { 2: 4, 5: 1 }, { 3: 3 }],
finalObj = {};
countObj.forEach(o => Object.keys(o).forEach(k => finalObj[k] > o[k] || (finalObj[k] = o[k])));
console.log(finalObj); // { 2:4, 3: 3, 5: 1 }
With primes
var countObj = [{ 2: 1 }, { 2: 4, 5: 1 }, { 3: 3 }],
finalObj = {},
primes = [2, 3, 5]
countObj.forEach(o => primes.forEach(k => k in o && (finalObj[k] > o[k] || (finalObj[k] = o[k]))));
console.log(finalObj); // { 2:4, 3: 3, 5: 1 }
Be careful with your tests: 0 is the same as a missing value. And when using reduce, you must return the accumulator object.
I'd reduce on the objects instead of reducing on the primes:
let finalObj = countObj.reduce((f, o)=>{
primes.forEach(k=>{
if (k in o && !(o[k]<f[k])) f[k]=o[k];
});
return f;
}, {});
You can use a nested foreach like this.
In this case you do not need primes[]
let countObj = [{
2: 1
}, {
2: 4,
5: 1
}, {
3: 3
}];
let finalObj = {};
let primes = [2, 3, 5];
countObj.forEach(function(obj) {
Object.keys(obj).forEach(function(key) {
var finalObjValue = finalObj[key] || 0;
if(obj[key] > finalObjValue)
finalObj[key] = obj[key];
});
});
console.log(finalObj);

Sort array into an object with key and value pairs with same values being pushed into the same key/value

I would like to sort an array into and object with key value pairs.
So if I had an array like this [1,2,3,2,4,1,5,1,6] it should spit out something like this. I was trying to use lodash for it!
{
1: [1, 1, 1],
2: [2, 2],
3: [3],
4: [4],
5: [5],
6: [6]
}
You can use reduce() and return object.
var ar = [1, 2, 3, 2, 4, 1, 5, 1, 6];
var result = ar.reduce(function(o, e) {
o[e] = (o[e] || []).concat(e);
return o;
}, {});
console.log(result)
Some basic iteration would do that, where you either set an array, or push to an existing array
var arr = [1,2,3,2,4,1,5,1,6];
var obj = {};
arr.forEach( (x) => x in obj ? obj[x].push(x) : obj[x] = [x]);
document.body.innerHTML = '<pre>'+ JSON.stringify(obj, 0, 4) +'</pre>'
const arr = [1,2,3,2,4,1,5,1,6];
const r = {};
arr.forEach(e=>r[e]?r[e].push(e):r[e]=[e]);
console.log(r);
Here is a very simple pure JavaScript version to achieve this (https://jsfiddle.net/azkuodyc/)
var array = [1,2,3,2,4,1,5,1,6];
var newArrayObject = {};
for (key in array) {
var value = array[key];
if (typeof newArrayObject[key] == 'undefined') {
newArrayObject[key] = [];
}
newArrayObject[key].push(value);
}
One other way of doing this is;
var arr = [1,2,3,2,4,1,5,1,6],
obj = arr.reduce((p,c) => (p[c] = p[c] ? p[c].concat(c) : [c],p),{});
console.log(obj);
var arr = [1,2,3,2,4,1,5,1,6];
var res = _(arr).countBy().mapValues((value, key) => {
return _.times(value, _.constant(parseInt(key)));
}).value();
console.log(res);
https://jsfiddle.net/7bppaxx5/

How to find duplicated values in an Array [duplicate]

I need to check a JavaScript array to see if there are any duplicate values. What's the easiest way to do this? I just need to find what the duplicated values are - I don't actually need their indexes or how many times they are duplicated.
I know I can loop through the array and check all the other values for a match, but it seems like there should be an easier way.
Similar question:
Get all unique values in a JavaScript array (remove duplicates)
You could sort the array and then run through it and then see if the next (or previous) index is the same as the current. Assuming your sort algorithm is good, this should be less than O(n2):
const findDuplicates = (arr) => {
let sorted_arr = arr.slice().sort(); // You can define the comparing function here.
// JS by default uses a crappy string compare.
// (we use slice to clone the array so the
// original array won't be modified)
let results = [];
for (let i = 0; i < sorted_arr.length - 1; i++) {
if (sorted_arr[i + 1] == sorted_arr[i]) {
results.push(sorted_arr[i]);
}
}
return results;
}
let duplicatedArray = [9, 9, 111, 2, 3, 4, 4, 5, 7];
console.log(`The duplicates in ${duplicatedArray} are ${findDuplicates(duplicatedArray)}`);
In case, if you are to return as a function for duplicates. This is for similar type of case.
Reference: https://stackoverflow.com/a/57532964/8119511
If you want to elimate the duplicates, try this great solution:
function eliminateDuplicates(arr) {
var i,
len = arr.length,
out = [],
obj = {};
for (i = 0; i < len; i++) {
obj[arr[i]] = 0;
}
for (i in obj) {
out.push(i);
}
return out;
}
console.log(eliminateDuplicates([1,6,7,3,6,8,1,3,4,5,1,7,2,6]))
Source:
http://dreaminginjavascript.wordpress.com/2008/08/22/eliminating-duplicates/
This is my answer from the duplicate thread (!):
When writing this entry 2014 - all examples were for-loops or jQuery. JavaScript has the perfect tools for this: sort, map and reduce.
Find duplicate items
var names = ['Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Nancy', 'Carl']
const uniq = names
.map((name) => {
return {
count: 1,
name: name
};
})
.reduce((result, b) => {
result[b.name] = (result[b.name] || 0) + b.count;
return result;
}, {});
const duplicates = Object.keys(uniq).filter((a) => uniq[a] > 1);
console.log(duplicates); // [ 'Nancy' ]
More functional syntax:
#Dmytro-Laptin pointed out some code that can be removed. This is a more compact version of the same code. Using some ES6 tricks and higher-order functions:
const names = ['Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Nancy', 'Carl'];
const count = names =>
names.reduce((result, value) => ({ ...result,
[value]: (result[value] || 0) + 1
}), {}); // don't forget to initialize the accumulator
const duplicates = dict =>
Object.keys(dict).filter((a) => dict[a] > 1);
console.log(count(names)); // { Mike: 1, Matt: 1, Nancy: 2, Adam: 1, Jenny: 1, Carl: 1 }
console.log(duplicates(count(names))); // [ 'Nancy' ]
UPDATED: Short one-liner to get the duplicates:
[1, 2, 2, 4, 3, 4].filter((e, i, a) => a.indexOf(e) !== i) // [2, 4]
To get the array without duplicates simply invert the condition:
[1, 2, 2, 4, 3, 4].filter((e, i, a) => a.indexOf(e) === i) // [1, 2, 3, 4]
Note that this answer’s main goal is to be short. If you need something performant for a big array, one possible solution is to sort your array first (if it is sortable) then do the following to get the same kind of results as above:
myHugeSortedArray.filter((e, i, a) => a[i-1] === e)
Here is an example for a 1 000 000 integers array:
const myHugeIntArrayWithDuplicates =
[...Array(1_000_000).keys()]
// adding two 0 and four 9 duplicates
.fill(0, 2, 4).fill(9, 10, 14)
console.time("time")
console.log(
myHugeIntArrayWithDuplicates
// a possible sorting method for integers
.sort((a, b) => a > b ? 1 : -1)
.filter((e, i, a) => a[i-1] === e)
)
console.timeEnd("time")
On my AMD Ryzen 7 5700G dev machine it outputs:
[ 0, 0, 9, 9, 9, 9 ]
time: 22.738ms
As pointed out in the comments both the short solution and the performant solution will return an array with several time the same duplicate if it occurs more than once in the original array:
[1, 1, 1, 2, 2, 2, 2].filter((e, i, a) => a.indexOf(e) !== i) // [1, 1, 2, 2, 2]
If unique duplicates are wanted then a function like
function duplicates(arr) {
return [...new Set(arr.filter((e, i, a) => a.indexOf(e) !== i))]
}
can be used so that duplicates([1, 1, 1, 2, 2, 2, 2]) returns [1, 2].
When all you need is to check that there are no duplicates as asked in this question you can use the every() method:
[1, 2, 3].every((e, i, a) => a.indexOf(e) === i) // true
[1, 2, 1].every((e, i, a) => a.indexOf(e) === i) // false
Note that every() doesn't work for IE 8 and below.
Find duplicate values in an array
This should be one of the shortest ways to actually find duplicate values in an array. As specifically asked for by the OP, this does not remove duplicates but finds them.
var input = [1, 2, 3, 1, 3, 1];
var duplicates = input.reduce(function(acc, el, i, arr) {
if (arr.indexOf(el) !== i && acc.indexOf(el) < 0) acc.push(el); return acc;
}, []);
document.write(duplicates); // = 1,3 (actual array == [1, 3])
This doesn't need sorting or any third party framework. It also doesn't need manual loops. It works with every value indexOf() (or to be clearer: the strict comparision operator) supports.
Because of reduce() and indexOf() it needs at least IE 9.
You can add this function, or tweak it and add it to Javascript's Array prototype:
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])
{
alert('this is a DUPE!');
continue o;
}
}
r[r.length] = this[i];
}
return r;
}
var arr = [1,2,2,3,3,4,5,6,2,3,7,8,5,9];
var unique = arr.unique();
alert(unique);
UPDATED: The following uses an optimized combined strategy. It optimizes primitive lookups to benefit from hash O(1) lookup time (running unique on an array of primitives is O(n)). Object lookups are optimized by tagging objects with a unique id while iterating through so so identifying duplicate objects is also O(1) per item and O(n) for the whole list. The only exception is items that are frozen, but those are rare and a fallback is provided using an array and indexOf.
var unique = function(){
var hasOwn = {}.hasOwnProperty,
toString = {}.toString,
uids = {};
function uid(){
var key = Math.random().toString(36).slice(2);
return key in uids ? uid() : uids[key] = key;
}
function unique(array){
var strings = {}, numbers = {}, others = {},
tagged = [], failed = [],
count = 0, i = array.length,
item, type;
var id = uid();
while (i--) {
item = array[i];
type = typeof item;
if (item == null || type !== 'object' && type !== 'function') {
// primitive
switch (type) {
case 'string': strings[item] = true; break;
case 'number': numbers[item] = true; break;
default: others[item] = item; break;
}
} else {
// object
if (!hasOwn.call(item, id)) {
try {
item[id] = true;
tagged[count++] = item;
} catch (e){
if (failed.indexOf(item) === -1)
failed[failed.length] = item;
}
}
}
}
// remove the tags
while (count--)
delete tagged[count][id];
tagged = tagged.concat(failed);
count = tagged.length;
// append primitives to results
for (i in strings)
if (hasOwn.call(strings, i))
tagged[count++] = i;
for (i in numbers)
if (hasOwn.call(numbers, i))
tagged[count++] = +i;
for (i in others)
if (hasOwn.call(others, i))
tagged[count++] = others[i];
return tagged;
}
return unique;
}();
If you have ES6 Collections available, then there is a much simpler and significantly faster version. (shim for IE9+ and other browsers here: https://github.com/Benvie/ES6-Harmony-Collections-Shim)
function unique(array){
var seen = new Set;
return array.filter(function(item){
if (!seen.has(item)) {
seen.add(item);
return true;
}
});
}
var a = ["a","a","b","c","c"];
a.filter(function(value,index,self){ return (self.indexOf(value) !== index )})
This should get you what you want, Just the duplicates.
function find_duplicates(arr) {
var len=arr.length,
out=[],
counts={};
for (var i=0;i<len;i++) {
var item = arr[i];
counts[item] = counts[item] >= 1 ? counts[item] + 1 : 1;
if (counts[item] === 2) {
out.push(item);
}
}
return out;
}
find_duplicates(['one',2,3,4,4,4,5,6,7,7,7,'pig','one']); // -> ['one',4,7] in no particular order.
Find non-unique values from 3 arrays (or more):
ES2015
// 🚩🚩 🚩 🚩 🚩
var arr = [1,2,2,3,3,4,5,6,2,3,7,8,5,22],
arr2 = [1,2,511,12,50],
arr3 = [22,0],
merged,
nonUnique;
// Combine all the arrays to a single one
merged = arr.concat(arr2, arr3)
// create a new (dirty) Array with only the non-unique items
nonUnique = merged.filter((item,i) => merged.includes(item, i+1))
// Cleanup - remove duplicate & empty items items
nonUnique = [...new Set(nonUnique)]
console.log(nonUnique)
PRE-ES2015:
In the below example I chose to superimpose a unique method on top of the Array prototype, allowing access from everywhere and has more "declarative" syntax. I do not recommend this approach on large projects, since it might very well collide with another method with the same custom name.
Array.prototype.unique = function () {
var arr = this.sort(), i=arr.length; // input must be sorted for this to work
while(i--)
arr[i] === arr[i-1] && arr.splice(i,1) // remove duplicate item
return arr
}
Array.prototype.nonunique = function () {
var arr = this.sort(), i=arr.length, res = []; // input must be sorted for this to work
while(i--)
arr[i] === arr[i-1] && (res.indexOf(arr[i]) == -1) && res.push(arr[i])
return res
}
// 🚩🚩 🚩 🚩 🚩
var arr = [1,2,2,3,3,4,5,6,2,3,7,8,5,22],
arr2 = [1,2,511,12,50],
arr3 = [22,0],
// merge all arrays & call custom Array Prototype - "unique"
unique = arr.concat(arr2, arr3).unique(),
nonunique = arr.concat(arr2, arr3).nonunique()
console.log(unique) // [1,12,2,22,3,4,5,50,511,6,7,8]
console.log(nonunique) // [1,12,2,22,3,4,5,50,511,6,7,8]
using underscore.js
function hasDuplicate(arr){
return (arr.length != _.uniq(arr).length);
}
The simplest and quickest way is to use the Set object:
const numbers = [1, 2, 3, 2, 4, 5, 5, 6];
const set = new Set(numbers);
const duplicates = numbers.filter(item => {
if (set.has(item)) {
set.delete(item);
return false;
} else {
return true;
}
});
// OR more concisely
const duplicates = numbers.filter(item => !set.delete(item));
console.log(duplicates);
// [ 2, 5 ]
This is my proposal (ES6):
let a = [1, 2, 3, 4, 2, 2, 4, 1, 5, 6]
let b = [...new Set(a.sort().filter((o, i) => o !== undefined && a[i + 1] !== undefined && o === a[i + 1]))]
// b is now [1, 2, 4]
Here's the simplest solution I could think of:
const arr = [-1, 2, 2, 2, 0, 0, 0, 500, -1, 'a', 'a', 'a']
const filtered = arr.filter((el, index) => arr.indexOf(el) !== index)
// => filtered = [ 2, 2, 0, 0, -1, 'a', 'a' ]
const duplicates = [...new Set(filtered)]
console.log(duplicates)
// => [ 2, 0, -1, 'a' ]
That's it.
Note:
It works with any numbers including 0, strings and negative numbers e.g. -1 -
Related question: Get all unique values in a JavaScript array (remove duplicates)
The original array arr is preserved (filter returns the new array instead of modifying the original)
The filtered array contains all duplicates; it can also contain more than 1 same value (e.g. our filtered array here is [ 2, 2, 0, 0, -1, 'a', 'a' ])
If you want to get only values that are duplicated (you don't want to have multiple duplicates with the same value) you can use [...new Set(filtered)] (ES6 has an object Set which can store only unique values)
Hope this helps.
Here is mine simple and one line solution.
It searches not unique elements first, then makes found array unique with the use of Set.
So we have array of duplicates in the end.
var array = [1, 2, 2, 3, 3, 4, 5, 6, 2, 3, 7, 8, 5, 22, 1, 2, 511, 12, 50, 22];
console.log([...new Set(
array.filter((value, index, self) => self.indexOf(value) !== index))]
);
Shortest vanilla JS:
[1,1,2,2,2,3].filter((v,i,a) => a.indexOf(v) !== i) // [1, 2, 2]
one liner simple way
var arr = [9,1,2,4,3,4,9]
console.log(arr.filter((ele,indx)=>indx!==arr.indexOf(ele))) //get the duplicates
console.log(arr.filter((ele,indx)=>indx===arr.indexOf(ele))) //remove the duplicates
var a = [324,3,32,5,52,2100,1,20,2,3,3,2,2,2,1,1,1].sort();
a.filter(function(v,i,o){return i&&v!==o[i-1]?v:0;});
or when added to the prototyp.chain of Array
//copy and paste: without error handling
Array.prototype.unique =
function(){return this.sort().filter(function(v,i,o){return i&&v!==o[i-1]?v:0;});}
See here: https://gist.github.com/1305056
Fast and elegant way using es6 object destructuring and reduce
It runs in O(n) (1 iteration over the array) and doesn't repeat values that appear more than 2 times
const arr = ['hi', 'hi', 'hi', 'bye', 'bye', 'asd']
const {
dup
} = arr.reduce(
(acc, curr) => {
acc.items[curr] = acc.items[curr] ? acc.items[curr] += 1 : 1
if (acc.items[curr] === 2) acc.dup.push(curr)
return acc
}, {
items: {},
dup: []
},
)
console.log(dup)
// ['hi', 'bye']
You can use filter method and indexOf() to get all the duplicate values
function duplicate(arr) {
return duplicateArray = arr.filter((item, index) => arr.indexOf(item) !== index)
}
arr.indexOf(item) will always return the first index at which a given element can be
found
ES5 only (i.e., it needs a filter() polyfill for IE8 and below):
var arrayToFilter = [ 4, 5, 5, 5, 2, 1, 3, 1, 1, 2, 1, 3 ];
arrayToFilter.
sort().
filter( function(me,i,arr){
return (i===0) || ( me !== arr[i-1] );
});
Here is a very light and easy way:
var codes = dc_1.split(',');
var i = codes.length;
while (i--) {
if (codes.indexOf(codes[i]) != i) {
codes.splice(i,1);
}
}
ES6 offers the Set data structure which is basically an array that doesn't accept duplicates.
With the Set data structure, there's a very easy way to find duplicates in an array (using only one loop).
Here's my code
function findDuplicate(arr) {
var set = new Set();
var duplicates = new Set();
for (let i = 0; i< arr.length; i++) {
var size = set.size;
set.add(arr[i]);
if (set.size === size) {
duplicates.add(arr[i]);
}
}
return duplicates;
}
With ES6 (or using Babel or Typescipt) you can simply do:
var duplicates = myArray.filter(i => myArray.filter(ii => ii === i).length > 1);
https://es6console.com/j58euhbt/
Simple code with ES6 syntax (return sorted array of duplicates):
let duplicates = a => {d=[]; a.sort((a,b) => a-b).reduce((a,b)=>{a==b&&!d.includes(a)&&d.push(a); return b}); return d};
How to use:
duplicates([1,2,3,10,10,2,3,3,10]);
I have just figured out a simple way to achieve this using an Array filter
var list = [9, 9, 111, 2, 3, 4, 4, 5, 7];
// Filter 1: to find all duplicates elements
var duplicates = list.filter(function(value,index,self) {
return self.indexOf(value) !== self.lastIndexOf(value) && self.indexOf(value) === index;
});
console.log(duplicates);
This answer might also be helpful, it leverages js reduce operator/method to remove duplicates from array.
const result = [1, 2, 2, 3, 3, 3, 3].reduce((x, y) => x.includes(y) ? x : [...x, y], []);
console.log(result);
Higher ranked answers have a few inherent issues including the use of legacy javascript, incorrect ordering or with only support for 2 duplicated items.
Here's a modern solution which fixes those problems:
const arrayNonUniq = array => {
if (!Array.isArray(array)) {
throw new TypeError("An array must be provided!")
}
return array.filter((value, index) => array.indexOf(value) === index && array.lastIndexOf(value) !== index)
}
arrayNonUniq([1, 1, 2, 3, 3])
//=> [1, 3]
arrayNonUniq(["foo", "foo", "bar", "foo"])
//=> ['foo']
You can also use the npm package array-non-uniq.
The following function (a variation of the eliminateDuplicates function already mentioned) seems to do the trick, returning test2,1,7,5 for the input ["test", "test2", "test2", 1, 1, 1, 2, 3, 4, 5, 6, 7, 7, 10, 22, 43, 1, 5, 8]
Note that the problem is stranger in JavaScript than in most other languages, because a JavaScript array can hold just about anything. Note that solutions that use sorting might need to provide an appropriate sorting function--I haven't tried that route yet.
This particular implementation works for (at least) strings and numbers.
function findDuplicates(arr) {
var i,
len=arr.length,
out=[],
obj={};
for (i=0;i<len;i++) {
if (obj[arr[i]] != null) {
if (!obj[arr[i]]) {
out.push(arr[i]);
obj[arr[i]] = 1;
}
} else {
obj[arr[i]] = 0;
}
}
return out;
}
var arr = [2, 1, 2, 2, 4, 4, 2, 5];
function returnDuplicates(arr) {
return arr.reduce(function(dupes, val, i) {
if (arr.indexOf(val) !== i && dupes.indexOf(val) === -1) {
dupes.push(val);
}
return dupes;
}, []);
}
alert(returnDuplicates(arr));
This function avoids the sorting step and uses the reduce() method to push duplicates to a new array if it doesn't already exist in it.

Categories