0

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;
3
  • Check if your sample file has some garbage strings on that line before pulling your hair out debugging your code. It's easier for you to debug, just add a breakpoints and go through the loop. Add a check to see if it's a valid date as well. Commented May 13, 2017 at 2:02
  • @JordanGS The sample data are the string items I trying to compare. I did a print to see what is inside the list Commented May 13, 2017 at 2:04
  • First I would take each element of the array, loop through to find all index number duplicates (for each item), and assign them to an int array. Then use a for loop on the int array, and add the totals items using the int indexes array as an index for the totals array. Third, I would add an if condition to check if the date has already been found and handled. Commented May 13, 2017 at 2:18

4 Answers 4

3

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++;
}
Sign up to request clarification or add additional context in comments.

5 Comments

you can combine the two computes into one with map.compute(tx.date(), (k, v) -> v == null ? tx.amt() : v + tx.amt()), Also LinkedHashMap might be better if you need to sort the map or iterate through it again later [citation needed]. And BigDecimal might be better than Double if dealing with currency but idk
Brilliant!! I will also add your idea!
@JunbangHuang So for the plotting part I should loop thru the map or?
@DeniseTan yes you can simply loop through the map using keyset.
Turns out Java 8 also happens to have the perfect Map collector for this, I added an example as an answer. @JunbangHuang
1

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));
    }
}

Comments

1

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>

Comments

1

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

}

2 Comments

So with this piece of code, when I try to loop thru the sorted list, which arraylist I should invoke? Is it tlist?
@DeniseTan sorry, I don't understand what you are asking in your comment. My tlist ArrayList ist a placeholder for your tlist. To plot the result you can use the Map directly, so there is no need to copy the values of the map to some other structure. You may have to sort the keys by date.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.