I wish to find unique points in a bunch of Point arrays (i.e. removing all the duplicates and seeing what is left).
Here is the code I have tried:
int numCount = 0;
for (int x = 0; x < ALLARRAYS.length; x++) {
for (final Point test : ALLARRAYS[x]) {
NUMBER: for (final Point[] numbers : ALLARRAYS) {
if (numbers == ALLARRAYS[x]) {
continue;
}
for (int i = 0; i < numbers.length; i++) {
if (test.equals(numbers[i])) {
break NUMBER;
} else {
if (i == numbers.length - 1) {
numCount++;
}
}
}
}
if (numCount == 10) {
System.out.println(x + "\tPoint: " + test.x + ", " + test.y + " is unique.");
}
numCount = 0;
}
System.out.println();
}
Basically, I have eleven arrays I want to check, therefore the numCount checks for 10 arrays to be confirmed. My approach was to cycle through each array, then cycle through all the points in that array, and then cycle through each point in every other array. If it sees a duplicate, it skips the whole number entirely.
My problem: I am getting false readings. I am not sure what is going on, but the program spits out points that already exist in other arrays.
My goal: Each array works as a whole. If one element is not satisfied, then the whole array is skipped. My end result should be 11 smaller-in-size arrays that are all unique so that a method can check through the elements of each set and determine that they are all unique.
NOTE: The arrays are all unique now, they are just ridiculously huge. I am looking for a way to truncate it by creating this mini-program to eliminate duplicates.
My question: Can someone please help me out?
3 Answers 3
Put all arrays entries in a Set, it will skip the duplicates.
Just be sure to correctly override the equals method on your Point class because the implementations of Set interface will use it.
HTH
-
that can work if he wants the union of the arrays in a new arrayLuiggi Mendoza– Luiggi Mendoza2012年05月04日 23:38:28 +00:00Commented May 4, 2012 at 23:38
-
1I am not looking for this. Please use my example above.Dylan Wheeler– Dylan Wheeler2012年05月04日 23:44:57 +00:00Commented May 4, 2012 at 23:44
-
I think a better approach would be to put the entries into a map from entry to number of times entry appeared in the arrays. The key could be an
Integer
or, if you're worried about object allocation, a mutableInteger
-type class. Once you have the Map created, you can iterate over the Map entries and get the ones whose count is 1.yshavit– yshavit2012年05月04日 23:47:45 +00:00Commented May 4, 2012 at 23:47
Your code appears to check all arrays for the Point
in question, including the array in which the Point
you're looking for appears. So, your code will always find the Point
it's looking for, and you will end up with no results.
You may need to do something like this:
NUMBER: for (final Point[] numbers : ALLARRAYS) {
if (numbers == array) {
continue; // skip the array that contains 'test'
}
...
}
That way, you will skip the array that contains the test
element.
-
@JavaCoder-1337 Greg's edit should cover it, provided you don't have any duplicate Points in a single array that you want to ignore.Anthony Grist– Anthony Grist2012年05月04日 23:47:04 +00:00Commented May 4, 2012 at 23:47
-
Your suggestion helped, but still gave me some duplicates. I have edited my original post including my current code.Dylan Wheeler– Dylan Wheeler2012年05月04日 23:51:15 +00:00Commented May 4, 2012 at 23:51
-
1The bulletproof answer is to test
(numbers == array && test == numbers[i])
in the inner loop. But why use two different styles offor
loop? No need for the counteri
. Re: being "too pushy," just be polite, and if you're asking entry-level questions you may want to reconsider "JavaCoder" and "1337" as a handle.Adam Liss– Adam Liss2012年05月04日 23:52:00 +00:00Commented May 4, 2012 at 23:52 -
1@JavaCoder-1337: Ok, so you've (a) moved the goalposts, invalidating the existing answers, and (b) continued to fail to provide sample data that demonstrates your problem. At this point we're having an increasingly difficult time replicating your problem, since we don't have all the information you do.Greg Hewgill– Greg Hewgill2012年05月04日 23:55:16 +00:00Commented May 4, 2012 at 23:55
Arrays aren't well suited for your job. Not only that they don't don't have methods like intersection or removeAll, they are hard to change, especially if you want to reduce their size.
To avoid this hassle, I mark a Point as removed
by setting x and y to -1, one coordinate would of course be enough, but for reasons of symmetry ...
import java.util.*;
import java.awt.Point;
public class RandPoints
{
Random r = new Random ();
Point [][] arr;
public void removeDuplicatesFrom2 (Point [] pa, Point [] pb) {
for (Point p : pb) {
if (p.x != - 1 && Arrays.asList (pa).contains (p)) {
// System.out.println ("dup: " + p.x + " " + p.y);
p.x = -1;
p.y = -1;
}
}
}
// create a random point in range (0..19)(0..19)
public Point randpoint () {
return new Point (r.nextInt (20), r.nextInt (20));
}
// create 10 (default) arrays of size 100 (default)
public void init (int arrsize, int arrcount)
{
arr = new Point [arrcount][];
for (int c = 0; c < arrcount; ++c)
{
Point [] points = new Point [arrsize];
for (int s = 0; s < arrsize; ++s)
{
Point p = randpoint ();
points[s] = p;
}
arr[c] = points;
}
}
public void unify ()
{
for (Point[] pac0 : arr) {
for (Point[] pac1 : arr)
{
if (pac0 != pac1)
removeDuplicatesFrom2 (pac0, pac1);
}
}
}
/**
fill arrays with duplicates by random,
show, delete and show again.
*/
public RandPoints (int arrsize, int arrcount)
{
init (arrsize, arrcount);
show ();
unify ();
System.out.println ();
show ();
}
public static void main (String args[])
{
int arrsize = 100;
int arrcount = 10;
if (args.length == 2)
{
arrsize = Integer.parseInt (args[0]);
arrcount = Integer.parseInt (args[1]);
}
new RandPoints (arrsize, arrcount);
}
// visible feedback is always welcome while debugging/testing
public void show ()
{
for (Point[] pa: arr) {
for (Point point: pa)
if (point.x != -1 && point.y != -1)
System.out.print (point.x + ", " + point.y + "\t");
System.out.println ();
}
}
}
I modified the code a bit, to make the maximum range for the values (20) configurable too.
Starting it with
java RandPoints 16 10 10
3, 0 9, 0 6, 9 2, 3 6, 9 7, 4 9, 9 2, 5 8, 7 3, 3 9, 5 3, 7 0, 5 7, 6 0, 4 8, 1
6, 1 2, 7 2, 5 6, 7 0, 7 5, 8 4, 2 1, 9 8, 4 5, 7 0, 2 3, 1 1, 9 2, 1 8, 0 1, 7
5, 4 9, 7 9, 3 7, 3 1, 2 9, 6 0, 4 6, 0 3, 0 7, 7 1, 3 1, 1 5, 3 3, 8 1, 0 4, 9
4, 7 8, 9 4, 0 0, 2 8, 7 5, 8 7, 0 1, 4 4, 9 8, 2 6, 9 9, 6 2, 1 1, 9 0, 8 6, 5
6, 8 9, 6 1, 0 6, 9 4, 0 5, 1 2, 9 7, 3 5, 1 2, 5 6, 9 0, 9 7, 4 8, 1 5, 5 3, 4
5, 9 0, 4 5, 4 2, 2 2, 6 7, 1 2, 0 6, 1 0, 4 9, 8 5, 7 5, 5 4, 6 9, 0 2, 8 8, 5
8, 2 4, 2 0, 8 1, 1 0, 3 3, 4 1, 8 3, 1 6, 6 4, 1 3, 6 6, 0 1, 7 4, 8 1, 6 1, 1
6, 2 1, 3 2, 4 0, 8 9, 0 3, 0 1, 1 3, 7 6, 2 2, 4 0, 9 3, 6 7, 2 1, 2 5, 0 8, 2
2, 3 5, 6 7, 9 3, 0 9, 3 2, 6 4, 8 8, 7 9, 4 5, 3 0, 3 3, 0 5, 5 1, 4 6, 4 5, 2
3, 2 4, 9 6, 9 4, 7 7, 1 0, 4 5, 8 7, 2 5, 2 5, 5 2, 1 9, 8 4, 9 6, 6 7, 7 0, 3
3, 0 9, 0 6, 9 2, 3 6, 9 7, 4 9, 9 2, 5 8, 7 3, 3 9, 5 3, 7 0, 5 7, 6 0, 4 8, 1
6, 1 2, 7 6, 7 0, 7 5, 8 4, 2 1, 9 8, 4 5, 7 0, 2 3, 1 1, 9 2, 1 8, 0 1, 7
5, 4 9, 7 9, 3 7, 3 1, 2 9, 6 6, 0 7, 7 1, 3 1, 1 5, 3 3, 8 1, 0 4, 9
4, 7 8, 9 4, 0 7, 0 1, 4 8, 2 0, 8 6, 5
6, 8 5, 1 2, 9 5, 1 0, 9 5, 5 3, 4
5, 9 2, 2 2, 6 7, 1 2, 0 9, 8 4, 6 2, 8 8, 5
0, 3 1, 8 6, 6 4, 1 3, 6 4, 8 1, 6
6, 2 2, 4 6, 2 2, 4 7, 2 5, 0
5, 6 7, 9 9, 4 6, 4 5, 2
3, 2
test == numbers[i]
. Point is a class, comparing it using the==
operator is only going to return true iftest
andnumbers[i]
have references that are the same. Try usingtest.equals(numbers[i])
instead?Point
to itself.