Count how many strings in an array have duplicates in the same array [duplicate] - javascript

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Array value count javascript
I have an array which contains several duplicates, what I'm trying to achieve is to count how many duplicates each unique string has in this one array.
The array looks something like this
array = ['aa','bb','cc','aa','ss','aa','bb'];
Thus I would like to do something like this
if (xWordOccurrences >= 5) {
// do something
}
But I'm not sure how I would code this.
I was thinking, create an object with each unique string, then loop through the original array, match each string with it's object and increment it's number by 1, then loop over the object to see which words had the most duplicates...
But this seems like an over complexe way to do it.

You can use an object which has keys of the Array's values and do something like this
// count everything
function getCounts(arr) {
var i = arr.length, // var to loop over
obj = {}; // obj to store results
while (i) obj[arr[--i]] = (obj[arr[i]] || 0) + 1; // count occurrences
return obj;
}
// get specific from everything
function getCount(word, arr) {
return getCounts(arr)[word] || 0;
}
getCount('aa', ['aa','bb','cc','aa','ss','aa','bb']);
// 3
If you only ever want to get one, then it'd be more a bit more efficient to use a modified version of getCounts which looks similar to getCount, I'll call it getCount2
function getCount2(word, arr) {
var i = arr.length, // var to loop over
j = 0; // number of hits
while (i) if (arr[--i] === word) ++j; // count occurance
return j;
}
getCount2('aa', ['aa','bb','cc','aa','ss','aa','bb']);
// 3

Try this function:
var countOccurrences = function(arr,value){
var len = arr.length;
var occur = 0;
for(var i=0;i<len;i++){
if(arr[i]===value){
occur++;
}
}
return occur;
}
var count = countOccurrences(['aaa','bbb','ccc','bbb','ddd'],'bbb'); //2
If you want, you can also add this function to the Array prototype:
Array.prototype.countOccurrences = function(value){
var len = this.length;
var occur = 0;
for(var i=0;i<len;i++){
if(this[i]===value){
occur++;
}
}
return occur;
}

How about you build an object with named property?
var array = ['aa','bb','cc','aa','ss','aa','bb'];
var summary = {};
var item = '';
for ( i in array){
item = array[i];
if(summary[item]){
summary[item] += 1;
}
else{
summary[item] = 1;
}
}
console.log( summary );
summary will contain like this
{aa: 3, bb: 2, cc: 1, ss: 1}
which you could then iterate on and then sort them later on if needed.
finally to get your count, you could use this summary['aa']

<script type="text/javascript">
var array = ['aa','bb','cc','aa','ss','aa','bb'];
var myMap = {};
for(i = 0; i < array.length; i++) {
var count = myMap[array[i]];
if(count != null) {
count++;
} else {
count = 1;
}
myMap[array[i]] = count;
}
// at this point in the script, the map now contains each unique array item and a count of its entries
</script>

Hope this solves your problem
var array = ['aa','bb','cc','aa','ss','aa','bb'];
var dups = {};
for (var i = 0, l = array.length; i < l; i++ ) {
dups[array[i]] = [];
}
for (str in dups) {
for (var i = 0, l = array.length; i < l; i++ ) {
if (str === array[i]) {
dups[str].push(str);
}
}
}
for (str in dups) {
console.log(str + ' has ' + (dups[str].length - 1) + ' duplicate(s)');
}

This function may do everything you need.
function countDupStr(arr, specifier) {
var count = {}, total = 0;
arr.forEach(function (v) {
count[v] = (count[v] || 0) + 1;
});
if(typeof specifier !== 'undefined') {
return count[specifier] - 1;
}
Object.keys(count).forEach(function (k) {
total += count[k] - 1;
});
return total;
}
Each value in the array is assigned and incremented to the count object. Whether or not a specifier was passed, the function will return duplicates of that specific string or the total number of duplicates. Note that this particular technique will only work on string-coercible values inside your arrays, as Javascript can only index objects by string.
What this means is that during object assignment, the keys will normalize down to strings and cannot be relied upon for uniqueness. That is to say, this function wouldn't be able to discern the difference between duplicates of 3 and '3'. To give an example, if I were to perform:
var o = {}, t = {};
o[t] = 1;
console.log(o);
The key used in place of t would eventually be t.toString(), thus resulting in the perhaps surprising object of {'[object Object]': 1}. Just something to keep in mind when working with Javascript properties.

I saw this post about it, perhaps it can help:
http://ryanbosinger.com/blog/2011/javascript-count-duplicates-in-an-array/

Related

calculate the occurence and store the result in a key value-pair using javascript

I need to calculate the occurence of the name in an array.
var eachAuthorData = ["bob","joke","hello","stack","stack","ok","joke","bob"];
I can do this by using a for loop,and get a result like this
{bob: 2, joke: 2, hello: 1, stack: 2, ok: 1}
but the result can only be access using
counts["bob"]
not only do I need to know the occrence of each name.
but also need to know how many diffent name in the array eachAuthorData
how do I locate bob in the eachAuthorData
I only need to use the name once
If you start with an array:
var eachAuthorData = ["bob","joke","hello","stack","stack","ok","joke","bob"];
and you want to know how many of each name there is in the array and how many unique strings there are, you can do it like this:
var counts = {}, i, item, uniques = 0;
for (i = 0; i < eachAuthorData.length; i++) {
item = eachAuthorData[i];
if (!counts.hasOwnProperty(item)) {
counts[item] = 1;
++uniques;
} else {
++counts[item];
}
}
This will generate an output in counts like this:
{bob: 2, joke: 2, hello: 1, stack: 2, ok: 1}
And, since you asked a few other questions in comments, I added the variable uniques which gives you the total unique string count.
And, you would access any individual count like this:
var cnt = counts["bob"];
Or, if the desired key is in a variable named key, you would use:
var cnt = counts[key];
If you want to iterate all the counts of all the unique strings, you can do that like this:
for (var item in counts) {
// item is the key
// counts[item] is the count
console.log("counts[" + item + "] = " + counts[item]);
}
Working demo: http://jsfiddle.net/jfriend00/eJyAg/
If you want a list of the keys in the counts object (e.g. the unique strings), you can use:
var keys = Object.keys(counts);
Object.keys() requires IE9 or greater or there's a polyfill here if you want interoperability with older versions of IE.
I think you should have:
var eachAuthorData = ["bob","joke","hello","stack","stack","ok","joke","bob"];
do this to count:
var toMatch, i, count;
toMatch = "bob";
count = 0;
for( i=0 ; i<eachAuthorData.length ; ++i ){
if( eachAuthorData[i] == toMatch ){
++count;
}
}
console.log("The element "+ toMatch +" is counted "+ count +" times!");
Try this one
var tempObject = new Object();
function count() {
array_elements = ["bob","joke","hello","stack","stack","ok","joke","bob"];
array_elements.sort();
var current = null;
var cnt = 0;
for (var i = 0; i < array_elements.length; i++) {
if (array_elements[i] != current) {
if (cnt > 0) {
tempObject[current]=cnt;
console.log(current + ' comes --> ' + cnt + ' times<br>');
}
current = array_elements[i];
cnt = 1;
} else {
cnt++;
}
}
if (cnt > 0) {
console.log(current + ' comes --> ' + cnt + ' times');
tempObject[current]=cnt;
}
}
count();
console.log(JSON.stringify(tempObject));
Presumably you meant an array like:
var data = ["bob","joke","hello","stack","stack","ok","joke","bob"];
Since others have gone the obvious route, I'll post something a little more robust that accounts for the possibility that the data array has elided members (i.e. is sparse):
function countMembers(dataArray) {
for (var i=0, iLen=dataArray.length, o={}, item; i<iLen; i++) {
item = dataArray[i];
if (dataArray.hasOwnProperty(i)) {
if (o.hasOwnProperty(item)) {
++o[item];
} else {
o[item] = 1;
}
}
}
return o;
}
Given:
["bob","joke",,,,"hello","stack","stack","ok","joke","bob"];
others will include a member undefined: 3, but the above wont.

Returning a missing element from a string of integers

I'm trying to write a function that accepts an array of unique integers between 0 and 9 (inclusive), and returns the missing element. Here's what I've got. So near but so far.
var currentPlace = 0;
function getMissingElement(superImportantArray){
while (currentPlace < 9){
for (var i = 0; i < 10; i++) {
var arrayNum = superImportantArray[currentPlace]
if (i == arrayNum) {
currentPlace ++;
console.log("so it's not " + i);
}
else if (i !=arrayNum) {
console.log("try..." + i);
}
}
}
}
// run
var myArray = [0,5,1,3,2,9,7,6,4]; // this test should return 8
getMissingElement(myArray);
I'm not sure i'm approaching this correctly. Thanks for your time.
Just wanted to post my answer from the comments. A simpler way to handle this, in my opinion, is to loop over the original array, and flag a new array at the index that they represent. For example, if the number is 4, flag the 4th index in the new array. The reason for all this is because once this is done, one index should be left unflagged. All that would be left to do is find the unflagged index.
Here's an example (I commented the code here, not the fiddle):
function findMissing(array, min, max) {
var missing, unfilledArray, i, j;
// Array to hold the flags
unfilledArray = [];
for (i = min, j = max; i <= j; i++) {
// Flag the index in the new array with the current value
unfilledArray[array[i]] = true;
}
for (i = min, j = max; i <= j; i++) {
// Loop over new array and find the unflagged index
currentUnfilled = unfilledArray[i];
if (!currentUnfilled) {
// Current index not flagged
missing = i;
break;
}
}
return missing;
}
DEMO: http://jsfiddle.net/6GAyw/
The other little feature I added was that you explicitly specify the minimum and maximum value, which, in your case, is 0 and 9. This feature allows this solution to be used on any range of numbers (unlike my original comment/suggestion).
And not that I fully understand big O notation, but I believe this is O(2n), not O(n^2), since there aren't nested loops/indexOf.
If you were looking to get all missing numbers in a range, you can easily modify the function to return an array of unflagged indexes instead. Here's an example:
function findMissing(array, min, max) {
var missing, unfilledArray, i, j;
// Array to hold the missing numbers
missing = [];
// Array to hold the flags
unfilledArray = [];
for (i = min, j = max; i <= j; i++) {
// Flag the index in the new array with the current value
unfilledArray[array[i]] = true;
}
for (i = min, j = max; i <= j; i++) {
// Loop over new array and find the unflagged index
currentUnfilled = unfilledArray[i];
if (!currentUnfilled) {
// Current index not flagged
missing.push(i);
}
}
return missing;
}
DEMO: http://jsfiddle.net/zFS89/
function getMissingElement(superImportantArray){
var result = [], length = Math.max(10, superImportantArray.length);
for (var i = 0; i < length; i++) {
if(superImportantArray.indexOf(i) == -1){
result.push(i);
}
}
return result;
}
Try this. This will return an array of missing elements else return an empty array.
DEMO FIDDLE
So here is one way to do it: Since you know that the array only contains values from 0 to 9, you can build a "set" of numbers and remove each "seen" value in the array from the set:
function getMissingElement(superImportantArray){
var numbers = {};
for (var i = 0; i < 10; i++) {
numbers[i] = true
}
for (var i = 0, l = superImportantArray.length; i < l; i++) {
delete numbers[superImportantArray[i]];
}
return Object.keys(numbers);
}
This would return an array of all numbers that are missing. If there can always only be one missing number you can easily modify this to directly return the number instead.
This should do it.
function getMissingElement(arrayTest) {
// create an array with all digits
var digitsArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var index;
for (var i=0; i<arrayTest.length; i++) {
// get the index of current digit on our array
index = digitsArray.indexOf(arrayTest[i]);
// if found, remove it from our array.
if (index >= 0) {
digitsArray.splice(index,1);
}
}
// the last remaining digit in the original array should be the one missing.
return (digitsArray[0]);
}
This one is better for the eyes.
function getMissingElement(superImportantArray) {
return superImportantArray.reduce(function (sum, value) {return sum - value;}, 45);
}

Remove duplicate element pairs from multidimensional array

I have an array that looks like this:
1. coordinates = [ [16.343345, 35.123523],
2. [14.325423, 34.632723],
3. [15.231512, 35.426914],
4. [16.343345, 35.123523],
5. [15.231512, 32.426914] ]
The latitude on line 5 is the same as on line 3, but they have different longitudes and are therefore not duplicates.
Both the latitude and longitude are the same on line 3 and 6, and are therefore duplicates and one should be removed.
The difficulty in this question that different arrays never compare equal even if they contain same values. Therefore direct comparison methods, like indexOf won't work.
The following pattern might be useful to solve this. Write a function (or use a built-in one) that converts arrays to scalar values and checks if these values are unique in a set.
uniq = function(items, key) {
var set = {};
return items.filter(function(item) {
var k = key ? key.apply(item) : item;
return k in set ? false : set[k] = true;
})
}
where key is a "hash" function that convert items (whatever they are) to comparable scalar values. In your particular example, it seems to be enough just to apply Array.join to arrays:
uniqueCoords = uniq(coordinates, [].join)
You can use standard javascript function splice for this.
for(var i = 0; i < coordinates.length; i++) {
for(var j = i + 1; j < coordinates.length; ) {
if(coordinates[i][0] == coordinates[j][0] && coordinates[i][1] == coordinates[j][1])
// Found the same. Remove it.
coordinates.splice(j, 1);
else
// No match. Go ahead.
j++;
}
}
However, if you have thousands of points it will work slowly, than you need to consider to sort values at first, then remove duplicates in one loop.
I rewrote the answer from thg435 (It does not allow me to post comments) and prototype it also using jQuery instead, so this will work on all browsers using it (Even IE7)
Array.prototype.uniq = function (key) {
var set = {};
return $.grep(this, function (item) {
var k = key
? key.apply(item)
: item;
return k in set
? false
: set[k] = true;
});
}
You can use it like:
arr = arr.uniq([].join);
If you are not on Safari this single liner could do the job
var arr = [[16.343345, 35.123523],
[14.325423, 34.632723],
[15.231512, 35.426914],
[16.343345, 35.123523],
[15.231512, 32.426914]],
lut = {},
red = arr.filter(a => lut[a] ? false : lut[a] = true);
document.write("<pre>" + JSON.stringify(red,null,2) + "</pre>");
It might be simpler to create another array keeping only unique coordinate pairs
var uniqueCoors = [];
var doneCoors = [];
for(var x = 0; x < coordinates.length; x++) {
var coorStr = coordinates[x].toString();
if(doneCoors.indexOf(coorStr) != -1) {
// coordinate already exist, ignore
continue;
}
doneCoors.push(coorStr);
uniqueCoors.push(coordinates[x]);
}
function sortCoordinates(arr){
var obj = {};
for(var i = 0, l = arr.length; i < l; i++){
var el = arr[i];
var lat = el[0];
var lng = el[1];
if(!obj[lat + lng]){
obj[lat + lng] = [lat, lng];
}
}
var out = [];
for(p in obj){
out.push([obj[p][0], obj[p][1]]);
}
return out;
}
I am not sure about coordinates[][] dataType. Make the comparison accordingly.
var dubJRows= new Array();
for(int i = 0; i < coordinates.length -2; i++){
for(int j = i+1; j < coordinates.length -1; j++){
if (i != j && chk_dubJRows_not_contains(j)) {
innerArray1 [1][1] = coordinates[i];
innerArray2 [1][1] = coordinates[j];
if ( innerArray1 [1][0] == innerArray2[1][0]
&& innerArray1[1][1] == innerArray2[1][1]) {
dubJRows.push(j);
}
}
}
}
//REMOVE ALL dubJRows from coordinates.

Removing duplicates in array of objects [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Remove duplicates from an array of objects in javascript
var arr = [{empID:100,empName:greg},{empID:101,empName:Math},{empID:100,empName:greg}];
var sorted_arr = arr.sort(); // You can define the comparing function here.
// JS by default uses a crappy string compare.
var results = [];
for (var i = 0; i < arr.length - 1; i++) {
if (sorted_arr[i + 1].empID != sorted_arr[i].empID) {
results.push(sorted_arr[i]);
}
}
alert(results);
I have an array of objects, but when i try to remove the duplicate object which matches the ID, it does not get removed. What's the issue with the code.
Your code has two problems:
the sorting does not really work
you forget to add the last element to the result
I would suggest the following alternative:
var arr = ...;
arr.sort( function( a, b){ return a.empID - b.empID; } );
// delete all duplicates from the array
for( var i=0; i<arr.length-1; i++ ) {
if ( arr[i].empID == arr[i+1].empID ) {
delete arr[i];
}
}
// remove the "undefined entries"
arr = arr.filter( function( el ){ return (typeof el !== "undefined"); } );
Provided that empID is guaranteed to be a string or number, I would skip the sorting step and use an object as a hash of IDs that have already been seen:
var arr = [
{empID:100,empName:"greg"},
{empID:101,empName:Math},
{empID:100,empName:"greg"}
];
var results = [];
var idsSeen = {}, idSeenValue = {};
for (var i = 0, len = arr.length, id; i < len; ++i) {
id = arr[i].empID;
if (idsSeen[id] !== idSeenValue) {
results.push(arr[i]);
idsSeen[id] = idSeenValue;
}
}
Your sort function should really use a comparator, if you're going to be comparing items n and n+1
var sorted_arr = arr.sort(function(a,b) { return a.empID - b.empID; } );
This way you can be assured that sequential items in the list can possibly have duplicate empID properties.

Create an array and check against it

I am not sure of how to do this, but what I want to do it create an array and be able to add new items to this array. Since the items are supposed to be a random number, when a new instance is created I would like it to be checked against the rest of the array and be sure that the number it has generated is not already in the array. How would I accomplish something like this?
I looked at Šime Vidas's answer and it seems to work, but I tried to shorten it to
var arr = [];
function add(a) {
var n = ~~(Math.random() * 100);
for (var i = 0; i < a.length; i++) {
if ( a[i] === n) { a.push(n) }
}
}
for (var i=0; i<5; i++){
add(arr)
}
document.getElementById('output').innerHTML += arr;
and I don't understand why this wouldn't work. It does pretty much the same thing, correct?
var arr = [];
function add(a) {
var n = ~~(Math.random() * 1000);
!is(a, n) && a.push(n);
}
function is(a, n) {
for (var i = 0; i < a.length; i++) {
if ( a[i] === n ) { return true; }
}
return false;
}
The add function creates a random integer number between 0 and 1000, and adds it to the array.
The is function checks whether the n number is somewhere inside the a array.
Demo: http://jsfiddle.net/kHhMp/2/
Demo 2: http://jsfiddle.net/kHhMp/3/
(Demo 2 shows that a number will only be added to the array if it's not already in it.)
btw
!is(a, n) && a.push(n);
is a short form of this:
if ( is(a, n) == false ) { a.push(n); }
The number is added to the array only if is(a, n) returns false.
UPDATE
var arr = [];
function add(a) {
var n = ~~(Math.random() * 1000),
ok = true;
for (var i = 0; i < a.length; i++) {
if ( a[i] === n ) { ok = false; }
}
ok && a.push(n);
}
If you enjoy fast code and you have many items in your array, you should use an Object rather than an Array.
Instead of doing var my_array=[]; my_array.push(my_number), use var my_object = {}; my_object[my_number] = true to add items in your structure.
With that approach, you can easily check if a new number is already in there with an if (my_object[my_number]) { /* already there */ } else { /* not there yet */ }
Once you're done, you can extract the list of numbers as an array by either using var keys = Object.keys(my_object), or if that's not available, var keys=[],i=0;for (keys[i++] in my_object);, more or less.
You may extend the built in Array object for your needs.
Array.prototype.pushUnique = function(value) {
var len = this.length;
for(var i = 0; i < len; i++) {
if(this[i]===value) return;
}
this.push(value);
}
var uniques = new Array();
uniques.pushUnique(1);
uniques.pushUnique(2);
uniques.pushUnique(1);
// array will contain only 1 and 2
The fastest, most cross-browser way is to iterate over the array using a loop:
var arr = [];
function addNum(num) {
for (i = 0, len = arr.length; i < len; i++) {
if ( arr[i] === num ) { return false; }
}
arr.push(num);
}
Be sure to get the length of the array before you run the loop so the length property isn't constantly checked.
var array = []
array[0] = 'Item'
array[0] === undefined
# returns false
array[1] === undefined
# returns true

Categories