DolceVita34
DolceVita34

Reputation: 115

Summing values within a nested map based on a key that's outside of the inner map

  import java.util.*;

public class Orders {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        Map<String, Map<Double, Double>> myMap = new LinkedHashMap<String, Map<Double, Double>>();


        String input = "";
        while (true) {

            input = scanner.nextLine();
            String[] tokens = input.split(" ");
            String name = tokens[0];
            if ("buy".equals(name)) {
                break;
            }
            double price = Double.parseDouble(tokens[1]);
            double quantity = Double.parseDouble(tokens[2]);
            Map<Double, Double> innerMap = myMap.get(name);
            myMap.put(name, innerMap = new HashMap<>());


            innerMap.put(price, quantity);
            Double existingQuantity = innerMap.get(price);

            if (myMap.containsKey(name)) {
                innerMap.replace(innerMap.get(price), price);
                myMap.get(name).put(price, existingQuantity + quantity);
            }



        }
        System.out.println(myMap);
    }
}

Hello,

What I'm trying to do here is sum the value(quantity) of innerMap for each time a repeating key(name) from the outer map is inputted. I did a lot of research but didn't manage to find a case similar to mine.

For example, an input of

Water 1.20 500
Water 1.20 300
buy

Should yield

Water 1.20 800

Also sorry for my english.

Upvotes: 3

Views: 321

Answers (3)

Eran
Eran

Reputation: 394146

It appears the you have to replace

innerMap.put(price, quantity);

with

innerMap.merge(price, quantity, (q1,q2)->q1+q2);

This way all the quantities that correspond with the same name and the same price will be summed.

It also appears that you should change

Map<Double, Double> innerMap = myMap.get(name);
myMap.put(name, innerMap = new HashMap<>());

to

Map<Double, Double> innerMap = myMap.get(name);
if (innerMap == null) {
    myMap.put(name, innerMap = new HashMap<>());
}

since you don't want to overwrite the inner Map of a given name each time you encounter that name.

To summarize:

while (true) {
    input = scanner.nextLine();
    String[] tokens = input.split(" ");
    String name = tokens[0];
    if ("buy".equals(name)) {
        break;
    }
    double price = Double.parseDouble(tokens[1]);
    double quantity = Double.parseDouble(tokens[2]);
    Map<Double, Double> innerMap = myMap.get(name);
    if (innerMap == null) {
        myMap.put(name, innerMap = new HashMap<>());
    }
    innerMap.merge(price, quantity, (q1,q2)->q1+q2);
}

And I believe this can be further simplified as follows:

while (true) {
    input = scanner.nextLine();
    String[] tokens = input.split(" ");
    String name = tokens[0];
    if ("buy".equals(name)) {
        break;
    }
    double price = Double.parseDouble(tokens[1]);
    double quantity = Double.parseDouble(tokens[2]);
    myMap.computeIfAbsent(name,n -> new HashMap<>())
         .merge(price, quantity, (q1,q2)->q1+q2);
}

EDIT: For your request in the comment you'll have to keep replacing the key of the inner Maps:

while (true) {
    input = scanner.nextLine();
    String[] tokens = input.split(" ");
    String name = tokens[0];
    if ("buy".equals(name)) {
        break;
    }
    double price = Double.parseDouble(tokens[1]);
    double quantity = Double.parseDouble(tokens[2]);
    Map<Double, Double> innerMap = myMap.computeIfAbsent(name,n -> new HashMap<>());
    if (innerMap.isEmpty()) {
        innerMap.put(price,quantity);
    } else {
        innerMap.put(price,quantity + innerMap.remove(innerMap.keySet().iterator().next()));
    }
}

Upvotes: 1

yousuf iqbal
yousuf iqbal

Reputation: 438

This will work

import java.util.*;

public class App {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        Map<String, Map<Double, Double>> myMap = new LinkedHashMap<String, Map<Double, Double>>();


        String input = "";
        while (true) {

            input = scanner.nextLine();
            String[] tokens = input.split(" ");
            String name = tokens[0];
            if ("buy".equals(name)) {
                break;
            }
            double price = Double.parseDouble(tokens[1]);
            double quantity = Double.parseDouble(tokens[2]);


            if(!myMap.containsKey(name)){
                myMap.put(name,new HashMap<>());

            }
            if(myMap.get(name).containsKey(price)){
                double previousQuantity  = myMap.get(name).get(price);
                myMap.get(name).put(price,previousQuantity+quantity);

            }
            else {

                myMap.get(name).put(price,quantity);

            }


        }
        System.out.println(myMap);
    }
}

Upvotes: 1

Esha
Esha

Reputation: 151

Hope. This helps

           if ("buy".equals(name)) 
           {
                break;
            }
            double price = Double.parseDouble(tokens[1]);
            double quantity = Double.parseDouble(tokens[2]);
            Map<Double, Double> innerMap = myMap.getOrDefault(name, new HashMap<>());
            Double existingQuantity = innerMap.getOrDefault(price, 0.0);
            innerMap.put(price, existingQuantity + quantity);
            myMap.put(name, innerMap);

Upvotes: 1

Related Questions