QWERTY
QWERTY

Reputation: 2315

Java sorting array with duplicate value

I got two array, one is dates and the other one is amount. What I am trying to do is if there is a record with same date, I will increase the amount rather than add another new item into the date.

Here is the code:

for (int i = 0; i < tlist.size(); i++) {
        Log.d("Dates", tlist.get(i).getTransactionDate());
        Log.d("Amt", String.valueOf(tlist.get(i).getTransactionAmt()));
        if(i == tlist.size()-1 || !tlist.get(i).getTransactionDate().equals(tlist.get(i+1).getTransactionDate()))
        {
            dates[i] = tlist.get(i).getTransactionDate();
            totals[i] = tlist.get(i).getTransactionAmt();
        }else{
            totals[i] += tlist.get(i).getTransactionAmt();
        }
    }

Sample data:

Dates: 06/05/2017
Amt: 20.0
Dates: 10/05/2017
Amt: 10.8
Dates: 15/05/2017
Amt: 12.0
Dates: 15/05/2017
Amt: 5.0

What I trying to acheive:

Dates: 06/05/2017
Amt: 20.0
Dates: 10/05/2017
Amt: 10.8
Dates: 15/05/2017
Amt: 17.0

When I try to plot it on graph (I am plotting directly using the items in dates and totals array), here is what I get:

Dates: 06/05/2017
Amt: 20.0
Dates: 10/05/2017
Amt: 10.8
Dates: (No label but have amount, this one supposed to be 15/05/2017)
Amt: 12.0
Dates: 15/05/2017
Amt: 0.0

for (int j = 0; j < totals.length; j++) {
        // This part plotting the line on the chart
        detailSeries.add(j, totals[j]);
        // This part setting the value at x-axis
        multiRenderer.addXTextLabel(j, dates[j]);
}

Any ideas?

EDIT

I tried to do this but I got index out of bound exception. I guess because I am +1 at the if condition:

if(!tlist.get(i).getTransactionDate().equals(tlist.get(i+1).getTransactionDate())) {
            dates[i] = tlist.get(i).getTransactionDate();
            amt = tlist.get(i).getTransactionAmt();
            if (tlist.size()-2 == i)
            {
                dates[i] = tlist.get(i+1).getTransactionDate();
                amt = tlist.get(i+1).getTransactionAmt();
            }
        }else{
            amt = tlist.get(i).getTransactionAmt() + tlist.get(i+1).getTransactionAmt();
        }
        totals[i] = amt;

Upvotes: 0

Views: 2541

Answers (4)

andih
andih

Reputation: 5603

The easiest way is to use a Map for this where you use the date as key and the amount as value.

Map ensures that the key only exists once.

A very simple (Java7 compatible) version of the algorithm may look something like this:

public static class A {
    public Date getTransactionDate() {
        return new Date();
    }
    public double getTransactionAmt()  {
        return 0;
    }
}

public static void main(String ...strings) {
    Map<Date, Double> map = new HashMap<>();
    ArrayList <A> tlist = new ArrayList<>();

    for (int i = 0; i < tlist.size(); i++) {
        A a = tlist.get(i);
        if (!map.containsKey(a)) {
            map.put(a.getTransactionDate(), a.getTransactionAmt());
        } else {
            double oldAmt = map.get(a.getTransactionDate());
            map.put(a.getTransactionDate(), oldAmt + a.getTransactionAmt());
        }
    }

    // copy the values of the map to the result structure

}

Upvotes: 1

Aarjav
Aarjav

Reputation: 1374

If you're using java 8 you can do this:

    tlist.stream().collect( Collectors.toMap( t -> t.getTransactionDate(), t -> t.getTransactionAmt(), (a, b) -> a + b ) );

for getting the Map<Date, Amount>

Upvotes: 1

Junbang Huang
Junbang Huang

Reputation: 1967

andih pretty much nailed it. In here, I provide another version written with Java Lambda. It does the same thing.

Map<Date, Double> map = new HashMap<Date, Double>();
for (int i = 0; i < tlist.size(); i++) {
    Log.d("Dates", tlist.get(i).getTransactionDate());
    Log.d("Amt", String.valueOf(tlist.get(i).getTransactionAmt()));
    Transaction tx = tlist.get(i);
    map.computeIfPresent(tx.getTransactionDate(), (key, oldVal) -> tx.getTransactionAmt() + oldVal);
    map.computeIfAbsent(tx.getTransactionDate(), key -> tx.getTransactionAmt());
}

As suggested by Aarjav, Here is a shorter version of my shorter version.

map.compute(tx.date(), (k, v) -> v == null ? tx.amt() : v + tx.amt())

For plotting:

int counter = 0;
for (Date k: map.keySet()) {
    // This part plotting the line on the chart
    detailSeries.add(counter, map.get(k));
    // This part setting the value at x-axis
    multiRenderer.addXTextLabel(counter, map.get(k));
    counter++;
}

Upvotes: 3

Fiddle Freak
Fiddle Freak

Reputation: 2041

Assuming the arrays of amt and dates are the same size, you can conjure function like this...

public static void printDatesAndAmts(String[] dates, double[] amt){
    ArrayList<String> datesWithoutDuplicates = new ArrayList<String>();
    ArrayList<String> datesChecked = new ArrayList<String>();
    ArrayList<Double> totals = new ArrayList<Double>();
    ArrayList<Integer> indexDuplicatesFound = new ArrayList<>();

    for (int i = 0; i < dates.length; i++){
        String tempDateItem = dates[i];
        double tempAmt = 0.0;
        for (int j = 0; j < dates.length; j++){
            if (tempDateItem.equals(dates[j]) && !(datesChecked.contains(tempDateItem))){
                indexDuplicatesFound.add(j);
                tempAmt += amt[j];
            }
        }
        if (!(datesWithoutDuplicates.contains(tempDateItem))){
            datesWithoutDuplicates.add(tempDateItem);
            totals.add(tempAmt);
        }
        datesChecked.add(tempDateItem);
        indexDuplicatesFound.clear();
    }

    for (int i = 0; i < datesWithoutDuplicates.size(); i++){
        System.out.println(datesWithoutDuplicates.get(i));
        System.out.println(totals.get(i));
    }
}

Upvotes: 1

Related Questions