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.
Related
I have a loop that has a function inside. my target here is to check if the current data inside the loop are still the same for example my array is like this
var data = ['test1','test1','test1','test2'];
now I will check them if the data on that array inside the loop are currently the same. for example like this.
for (var i = 0; i < data.length; i++) {
var value = data[i][0];
console.log(checkifcurrent(value));
}
my problem here is to return checkifcurrent(value) if it still the same like this
function checkifcurrent(value) {
if (currentvalue is still the same as the last one) {
console.log(same);
} else {
console.log(not same);
}
}
I hope you understand tysm for understanding
You can do it like this, no need for a function call.
var data = ['test1','test1','test1','test2'];
lastValue = data[0];
for (var i = 1; i < data.length; i++) {
var currentValue = data[i];
if(lastValue==currentValue){
console.log("Value is same")
}
else
{
console.log("Value is not same")
}
lastValue = currentValue;
}
you can iterate over the data array and compare with all the array elements except the one at the current position.
If it is equals to the current and the index is not the same of the current then it is a duplicate
var data = ['test1','test1','test1','test2'];
for (var i = 0; i < data.length; i++) {
var value = data[i];
for(var j = 0; j < data.length; j++){
//skip the index at position i, because it is the one we are currently comparing
if(i !== j && data[j] === value) {
console.log('another value like: ' + value + ' at position: ' + i + ' has been found at index: ' + j)
}
}
}
Its not very clear about your task, i hope it is checking if the a value present in arr1 is available are not in arr2. If you so,
Loop through all elements in arr1 and check the indexof it
arr1 =[1,2,3,4];
arr2 = [2,3,4,5,6,6];
arr1.forEach((x)=>{if(arr2.indexOf(x)==-1){console.log('unable to find the element'+x)}})
unable to find the element1
var isSame = (function () {
var previous;
return function(value){
var result = value === previous;
previous = value;
return result;
}
})();
Alternatively you can use lodash difference function to compare old and new array.
http://devdocs.io/lodash~4/index#difference
For example:
const _ = require('lodash')
// Save the old array somewhere
let oldArray = ['test1','test1','test1','test2']
let newArray = ['test1','test1','test1','test3']
const areParametersTheSame = !!(_.difference(oldArray, newArray))
I have a nice riddle that I would like to see solved. There might be a better way of doing this and i am open for idea's.
I am trying to write an undo function for a canvas drawing app.
I have the following object, within it an array with their own objects with three properties.
var allDamages= {};
allDamages['scratch'] = [];
allDamages['scratch'].push({"x":4,"y":6,"index":1});
allDamages['scratch'].push({"x":3,"y":3,"index":2});
allDamages['scratch'].push({"x":9,"y":9,"index":3});
allDamages['scratch'].push({"x":19,"y":39,"index":4});
allDamages['dent'] = [];
allDamages['dent'].push({"x":59,"y":69,"index":5});
allDamages['dent'].push({"x":59,"y":69,"index":9});
allDamages['dent'].push({"x":39,"y":19,"index":6});
allDamages['rip'] = [];
allDamages['rip'].push({"x":20,"y":22,"index":7});
allDamages['rip'].push({"x":100,"y":56,"index":8});
I want to remove the last entry from this array. I want to do this by the property 'index'.
So I need to somehow find the entry which has the highest value of the property 'index' and then remove it from the array. What is the best way in doing this?
Greetings,
Robert
allDamages.scratch.length -1 returns the last index for that array.
Edit:
allDamages.scratch.slice(-1).pop() returns the last array item.
And if you just want to remove the last item in your array you should (like Givi said) use the pop() method on a sorted array like so:
allDamages['scratch'].pop()
Edit2:
Because the question wasn't clear for me. This is my final shot at the problem.
var allDamagesInOneArray = [];
for(array in allDamages){
allDamagesInOneArray.concat(array);//Assuming every key is an array
}
allDamagesInOneArray.sort(function(a,b){
return a.index - b.index;
});
var lastObj = allDamagesInOneArray.slice(-1).pop(); //element with latest index
I think you should create an object that save three your properties. After that you create a stack for undo. Like this:
function yourObject(x,y,index){
this.x = x; this.y = y; this.index = index;
}
var yourStack = new Array();
yourStack.push(new yourObject(4, 6, 1));
If the highest index in an array is always the last element of the array:
allDamages.scratch = allDamages.scratch.slice(0, allDamages.scratch.length - 1);
This removes the last element of the array
If index is not incrementing or if you always want to remove the latest index, no matter in which of the damages arrays it is (as I'd guess) you can use this function:
var undo = function(input){
var max= 0;
var undoType = "";
var undoIndex = 0;
for( var type in input ) {
// type: string
var locations = input[type];
// locations: array
// find the location of the heighest index property.
for( var i = 0; i < locations.length; i++ ) {
if( locations[i]["index"] > max) {
max = locations[i]["index"] ;
undoType = type;
undoIndex = index;
}
}
}
var output = input[type].splice(undoIndex, 1);
return output;
}
This should remove the element with the largest "index" property from your damage array.
First off, store a counter for highest index property found in the objects, and the index of that object within the scratch array.
var highestIndex = -Infinity;
var indexInArray
Then if you're using jQuery:
$.each( allDamages.scratch, function highestIndex( index, object ){
if( object.index > highestIndex ){
highestIndex = object.index;
indexInArray = index;
}
} );
Or, if not:
for( var indexCounter = 0, indexCounter < allDamages.scratch, indexCounter++ ){
if( allDamanges.scratch[ indexCounter ].index > highestIndex ){
highestIndex = allDamages.scratch[ indexCounter ].index;
indexInArray = indexCounter;
}
};
Try:
var allDamages= {};
allDamages['scratch'] = [];
allDamages['scratch'].push({"x":4,"y":6,"index":1});
allDamages['scratch'].push({"x":3,"y":3,"index":2});
allDamages['scratch'].push({"x":9,"y":9,"index":3});
allDamages['scratch'].push({"x":19,"y":39,"index":4});
allDamages['dent'] = [];
allDamages['dent'].push({"x":59,"y":69,"index":5});
allDamages['dent'].push({"x":59,"y":69,"index":9});
allDamages['dent'].push({"x":39,"y":19,"index":6});
allDamages['rip'] = [];
allDamages['rip'].push({"x":20,"y":22,"index":7});
allDamages['rip'].push({"x":100,"y":56,"index":8});
var index;
var cnt = 0;
var val;
$.each(allDamages,function(k,v){
if(cnt == 0){
index = highest(v); //get highest value from each object of allDamages
val = k;
}
else{
if(highest(v) > index){
index = highest(v);
val = k;
}
}
cnt++;
});
console.log("highest : "+index+": "+val);
var len = allDamages[val].length;
for(var i=0;i<len;i++){
if(allDamages[val][i].index == index){
allDamages[val].splice(i,1); //remove object having highest value
break;
}
}
console.log(allDamages);
function highest(ary) {
var high = ary[0].index;
var len = ary.length;
if(len > 0){
for(var i=0;i<len;i++){
if(ary[i].index > high){
high = ary[i].index;
}
}
}
return high;
}
DEMO here.
I've simplified my array to:
allDamages.push({"x":39,"y":19,"index":6,"type":'dent'});
That way i can use .pop() function in a normal way.
Thank you all for the quick response!!!
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/
UPDATED
I've got an object var myObject = {};
I build it using a key like so:
myObject[key] = {
name: ...
};
So imagine I have created three records:
myObject[13] = {...};
myObject[281] = {...};
myObject[76] = {...};
I now want to loop through the object as if it were an array.
var i,
length = myObject.length; // ?? Problem here 'cos it ain't an array
for (i = 0; i < length; i += 1) {
????
};
How can I refer to the three elements at ????? I don't know the numbers 13, 281 & 76, and myObject[0] is not going to find the first record.
Thanks.
You shouldn't be using an array if your keys aren't consecutive. Use an object instead:
var myObject = {};
To loop over an object's keys, you use the for..in syntax:
for (var key in myObject) {
var value = myObject[key];
}
To make your current code work, you'd have to loop over all of the keys and check to see if they have values:
for (var i = 0; i < myArray.length; i++) {
var value = myArray[i];
if (typeof value === 'undefined') continue;
console.log(key, ' -> ', value)
}
If you're using a modern JavaScript engine:
myArray.forEach(function(val, key) {
// val = the value
// key = the index
});
And that's it. To get its size (3, in this case)...
var size = myArray.reduce(function(prev) {
return ++prev;
}, 0);
If you want this to work in older browsers, you'll need to do something else. The easiest solution would probably be to implement something like this yourself:
for (var i = 0; i < myArray.length; i ++) {
var val = myArray[i];
if (typeof val !== "undefined") {
console.log(val);
}
}
To get its size, it's a similar endeavor (that you could combine with the above method if you're doing both):
var size = 0;
for (var i = 0; i < myArray.length; i ++) {
if (typeof myArray[i] !== "undefined")
size ++;
}
If you want to use forEach and reduce like the above, you'll need to find a shim (basically, you'll need to implement those functions yourself). I'd recommend the larger of the two forEach shims on this page and the reduce shim on this page, or use a library that shims them all.
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