nhunston
nhunston

Reputation: 1367

How can I flag duplicates in an array?

I would like to know a method for flagging values in an array, removing the duplicates and combining some of the data in Java.

I am keeping a record of geo locations using lat, long and description this is encoded in a JSON array as follows:

[{"lon": 0.001, "lat": 0.001, "desc": test}, {"lon": 0.001, "lat": 0.001, "desc": test2}]

I would like to be able to remove the duplicate geo locations while keeping the "desc" part of the array, e.g.

[{"lon": 0.001, "lat": 0.001, "desc": test, test2}]

Edit: This is what I am currently doing:

//Store locPoints from server in JSONArray
JSONArray jPointsArray = new JSONArray(serverData); 
List<JSONObject> jObjects = new ArrayList<JSONObject>();
List<JSONObject> seenObjects = new ArrayList<JSONObject>();

 for(int i = 0; i < jPointsArray.length(); ++i)
{
 jObjects.add(jPointsArray.getJSONObject(i));
}        
 for (JSONObject obj : jObjects) 
                {
                    //This always returns true
                    if (!seenObjects.contains(obj))// && !seenObjects.contains(obj.get("lon")))
                    {

                        Log.i("Sucess", "Huzzah!");
                        seenObjects.add(obj);
                    }
                    else 
                    {
                         //merge the 'desc' field in 'obj' with the 'desc' field in
                         JSONObject original = (JSONObject)seenObjects.get(seenObjects.indexOf(obj));
                         JSONObject update = obj;
                         original.put("desc", original.get("desc") + ", " + update.get("desc"));
                         seenObjects.get(seenObjects.indexOf(obj)).get("desc"));

                    }
                }

Upvotes: 0

Views: 1084

Answers (2)

Nishant
Nishant

Reputation: 55866

You can use GSon. And follow the steps:

1. Define an equivalent POJO in Java, to map the JSON String

public class Location implements Comparable<Location> {
    public String lon;
    public String lat;
    public String desc;

    @Override
    public String toString() {
        return "<lon: " + lon +", lat: "+ lat +", desc: " + desc +">";
    }

    @Override
    public boolean equals(Object obj) {
        return ((Location)obj).lon.equals(lon) && ((Location)obj).lat.equals(lat); 
    }

    public int compareTo(Location obj) {
        return ((Location)obj).lon.compareTo(lon) + ((Location)obj).lat.compareTo(lat);
    }


}

2. Write the code that merges similar location. OK, it's Sunday, lets do it :)

public static void main(String[] args){
      //Some test data
    String s = "[" +
            " {\"lon\": 0.001, \"lat\": 0.001, \"desc\": \"test\"}," +
            " {\"lon\": 0.002, \"lat\": 0.001, \"desc\": \"test3\"}," +
            " {\"lon\": 0.002, \"lat\": 0.005, \"desc\": \"test4\"}," +
            " {\"lon\": 0.002, \"lat\": 0.001, \"desc\": \"test5\"}," +
            " {\"lon\": 0.001, \"lat\": 0.001, \"desc\": \"test2\"}]";
    Gson gson = new Gson();
    Location[] al = gson.fromJson(s, Location[].class);
    List<Location> tl = Arrays.asList(al);

     //lets sort so that similar locations are grouped
    Collections.sort(tl);
    List<Location> fl = new ArrayList<Location>();
    Location current = null;

     //merge!
    for(Iterator<Location> it = tl.iterator(); it.hasNext();){
        current = current==null?it.next():current;
        Location ltmp = null;
        while(it.hasNext() && (ltmp = it.next()).equals(current))
            current.desc = current.desc + "," + ltmp.desc;
        fl.add(current);
        current = ltmp;
    }

       //convert back to JSON?
    System.out.println(gson.toJson(fl));

}

3. output

[{"lon":"0.002","lat":"0.005","desc":"test4"},
{"lon":"0.002","lat":"0.001","desc":"test3,test5"},
{"lon":"0.001","lat":"0.001","desc":"test,test2"}]

Upvotes: 2

aroth
aroth

Reputation: 54806

You could do something like:

//assuming that the array you are filtering is called 'myArray'
List<Object> seenObjects = new ArrayList<Object>();
for (Object obj : myArray) {
    if (! seenObjects.contains(obj)) {
        seenObjects.add(obj);
    }
    else {
        //merge the 'desc' field in 'obj' with the 'desc' field in
        //'seenObjects.get(seenObjects.indexOf(obj))'
    }
}

Note that this will only work if the objects you are comparing have implementations of equals() and hashCode() that do what you want (in your case, they should only take into consideration the 'lat' and 'lon' fields).

Update:

Here is some complete example code:

import java.util.ArrayList;
import java.util.List;

import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

public class JsonMergeTest {
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static void main(String[] args) {
        List<Object> myArray = new ArrayList<Object>();
        myArray.add(MyJsonObject.parse("{\"lon\": 0.001, \"lat\": 0.001, \"desc\": \"test\"}"));
        myArray.add(MyJsonObject.parse("{\"lon\": 0.001, \"lat\": 0.001, \"desc\": \"test2\"}"));

        List seenObjects = new ArrayList<Object>();
        for (Object obj : myArray) {
            if (! seenObjects.contains(obj)) {
                seenObjects.add(obj);
            }
            else {
                //merge the 'desc' field in 'obj' with the 'desc' field in the list
                MyJsonObject original = (MyJsonObject)seenObjects.get(seenObjects.indexOf(obj));
                MyJsonObject update = (MyJsonObject)obj;
                original.put("desc", original.get("desc") + ", " + update.get("desc"));
            }
        }

        for (MyJsonObject obj : (List<MyJsonObject>)seenObjects) {
            System.out.println(obj.toJSONString());
        }
    }

    private static class MyJsonObject extends JSONObject  {
        @Override
        public boolean equals(Object obj) {
            if (obj == null || ! (obj instanceof MyJsonObject) || ! this.containsKey("lat") || ! this.containsKey("lon")) {
                return super.equals(obj);
            }
            MyJsonObject jsonObj = (MyJsonObject)obj;
            return this.get("lat").equals(jsonObj.get("lat")) && this.get("lon").equals(jsonObj.get("lon"));
        }

        @Override
        public int hashCode() {
            if (! this.containsKey("lat") || ! this.containsKey("lon")) {
                return super.hashCode();
            }
            return this.get("lat").hashCode() ^ this.get("lon").hashCode();
        }

        @SuppressWarnings("unchecked")
        public static Object parse(String json) {
            Object parsedJson = JSONValue.parse(json);
            if (! (parsedJson instanceof JSONObject)) {
                return parsedJson;
            }

            MyJsonObject result = new MyJsonObject();
            result.putAll((JSONObject)parsedJson);
            return result;
        }
    }
}

Upvotes: 2

Related Questions