简体   繁体   中英

Java mapping data from two arrays and insert into third array

I am having difficulty mapping the data in two lists into a third list. My sample data is as follows:

Categorylist ID:  1,2,3,4,5,6,7,8,9,10,42,46,49,50
CurrentMonthByCat ID: 1,2,3,4,5,6,7,8,9,10,42,49,50
(the transaction amount value for CurrentMonthByCat: 92,46,40,180,60,10,1510,200,500,10,234,12)

There is a missing 46 in the currentMonthByCat. I am trying to do it in a way such that if the currentMonthByCat ID does not exist from the categorylist ID, I will insert 0 into the third list rather than getting the transaction amount from CurrentMonthByCat and push it into the third list.

ArrayList<Double> total = new ArrayList<Double>();

    for(int i = 0; i < categorylist.size(); i++){
        for(int j = 0; j < currentMonthByCat.size(); j++){
            if(categorylist.get(i).getCategoryID().equals(currentMonthByCat.get(j).getCategory().getCategoryID())){
                Log.d("IIIII", categorylist.get(i).getCategoryID());
                Log.d("JJJJJ", currentMonthByCat.get(j).getCategory().getCategoryID());
                total.add((double)currentMonthByCat.get(j).getTransactionAmt());
            }else{
                total.add(0.0);
            }
        }
    }

    for(int k = 0; k < total.size(); k++){
        Log.d("KKKKK", String.valueOf(total.get(k)));
    }

But the printed out result of total list is:

  92,0,0,0,0,0,0,0,0,0,0,0,0,0,46,0,0,0...

What I expected is:

  92,46,40,180,60,10,1510,200,500,10,0,234,12

I wanted to insert 0 only if the ID in currentMonthByCat does not match the ID in categorylist. For instance, the ID 46 which is the 3rd position from the right.

I realized the reason is because firstly I inserted 92 into third array, then the categorylist ID is still at 1, then it will compare with all the rest in the currentMonthByCat before moving to ID 2. That is why the unnecessary zeros. But I not sure how to actually sort it to achieve what I wanted.

Any ideas?

Thanks in advance.

Put your values into Map<Integer, Double>

Map<Integer, Double> map = new HashMap<Integer, Double>();
for (int i = 0; i < currentMonthByCat.size(); ++i) {
    //... categoryId = currentMonthByCat.get(i).categoryId
    //... amount = currentMonthByCat.get(i).amount
    map.put(categoryId, amount);
}

Then traverse the map using values from Categorylist ID:

// create result arraylist
ArrayList<Double> total = new ArrayList<Double>();
for (int i = 0; i < categorylist.size(); ++i) {
    Double amount = map.get(categorylist.get(i));
    if (amount == null) {
        total.add(0.0);
    } else {
        total.add(amount);
    }
}

The result list total will contain amounts for existing mappings, or zeros for non-existent.

Other way If it is guaranteed categorylist is sorted and CurrentMonthByCat is sorted

you can then traverse one of the lists while keeping index/cursor to the other list and not iterating the other list from the beginning, but from previously remembered cursor value, resulting in better average performance than n^2

It's easy one. you can't take a decision of adding zero or value in the total array unless the inner loop finish. so probably you add element existAtIndex and initialize it with -1 and in the loop if you find the element then assign the index to existAtIndex and break the loop or if it's not exist then you add zero. so the code will be something like :

ArrayList<Double> total = new ArrayList<Double>();
int existAtIndex;
    for(int i = 0; i < categorylist.size(); i++){
        // search for the element index
        existAtIndex = -1;
        for(int j = 0; j < currentMonthByCat.size(); j++){
            if(categorylist.get(i).getCategoryID().equals(currentMonthByCat.get(j).getCategory().getCategoryID())){

                existAtIndex = j;
                break;
            }
        }

        // add the value in the element index or add zero if the element not exist
        if (existAtIndex != -1) {
          total.add((double)currentMonthByCat.get(existAtIndex).getTransactionAmt());
        }
        else {
            total.add(0.0);
        }
    }

    for(int k = 0; k < total.size(); k++){
        Log.d(String.valueOf(total.get(k)));
    }

For better code you could use contains method to check for the item if exist or not in arrayList instead of using the basic loop. Good luck

You have a lot of code for what you are trying to do here. I think the following snippet does what you want in a very readable and maintainable way.

    //First of all we are interested in getting a transaction amount for each value in currentMonthByCat
    //so loop around using your object (not sure what it's called)
    for(CurrentMonth value : currentMonthByCat){
        //check if it's present. 
        //We create a new method here that gets you your category list as a list of integers. 
        //This is key to making the whole method much more readable.
        if(categorylist.getIdsAsList().contains(value.getCategory().getCategoryID())){
            //it is so add it
            total.add(value.getTransactionAmt());
        } else {
            //it's not so add a 0
            total.add(0.0);
        }
    }

The getIdsAsList method could look like this:

public List<Integer> getIdsAsList(){
    List<Integer> result = new ArrayList<>();
    for (CategoryListItem item : categorylist) {
        result.add(item.getCategoryId());
    }
    return result;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM