0

I am having trouble isolating each different name and calculating the avg, min, max for those. I have no problem if it was just doing it for one list, but when I have to use the values from only certain names that's when it gets tricky.

public static ArrayList<Double> summarizeData (
    ArrayList<String> names, 
    ArrayList<Double> values,  
    ArrayList<String> categories, 
    int operation)
{
}

so for finding the avg I would do something similar to:

            //calculate sum of all array elements
            int sum = 0;

            for(int i=0; i < summarizeData.length ; i++)
                    sum = sum + summarizeData[i];

            //calculate average value
            double average = sum / summarizeData.length;

The list of values I have are as follows:

Utah        5
Nevada      6
California  12
Oregon      8
Utah        9
California  10
Nevada      4
Nevada      4
Oregon      17
California  6

The values are coming from a Junit test case so I can't use ones that are declared with a method but rather they have to be able to pass any test cases given.

Jay S
  • 3
  • 5

2 Answers2

2

These kinds of calculations have gotten quite a bit easier with Java 8. Assuming you have the following wrapper class to wrap your data:

class Data {
    final String name;
    final int value;

    public Data(String name, int value) {
        this.name = name;
        this.value = value;
    }
}

You can now run:

Stream.of(new Data("Utah"        ,5 ),
          new Data("Nevada"      ,6 ),
          new Data("California"  ,12),
          new Data("Oregon"      ,8 ),
          new Data("Utah"        ,9 ),
          new Data("California"  ,10),
          new Data("Nevada"      ,4 ),
          new Data("Nevada"      ,4 ),
          new Data("Oregon"      ,17),
          new Data("California"  ,6 ))
      .collect(Collectors.groupingBy(
          d -> d.name,
          Collectors.summarizingInt(d -> d.value)))
      .forEach((name, summary) -> System.out.println(name + ": " + summary));

Which yields:

Oregon: IntSummaryStatistics{count=2, sum=25, min=8, average=12.500000, max=17}
California: IntSummaryStatistics{count=3, sum=28, min=6, average=9.333333, max=12}
Utah: IntSummaryStatistics{count=2, sum=14, min=5, average=7.000000, max=9}
Nevada: IntSummaryStatistics{count=3, sum=14, min=4, average=4.666667, max=6}
Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509
0

A simplistic version using ArrayLists could go like:

List<Integer> ints = new ArrayList<Integer>(); 

// Populate the list with some stuff
ints.add(5);
ints.add(20);

int sum = 0;

for (Integer anInt : ints) { // For each Integer in ints
    sum += anInt; // Add it's value to the sum
}

double average = sum / ints.size();

Note the use of java's for-each or enhanced for loop for an ArrayList which greatly simplifies iteration. Also note that ArrayList cannot accept a primitive type for it's generic type, so we must take advantage of autoboxing and use the boxed type Integer. Lastly, notice that the ArrayList object is being declared as a List but instantiated as an ArrayList.

If your values are strings that contain ints among other things. Then inside your loop you'll have to separate them. Regex would be a good tool for this. After a quick search, the accepted answer here looks like it solves it just fine number out of string in java

Edit:

This answer is too simple to as it doesn't care what the context of the data is. If you want to have each state have it's own set of stats. You could store them in a Map<String, Integer> to pair the sum of each state with the name of that state.

Map<String, Integer> stateSums = new HashMap<String, Integer>();

stateSums.put("Oregon", 17);
stateSums.put("Utah", 9); //etc

Keep in mind that the put method will override an existing value if it's key already exists. So if you wanted to add a new value to the existing oregon key, you'd do something like: stateSums.put("Oregon", stateSums.get("Oregon") + 8);

Lets say you wanted to sort them but keep all their values completely separate! You can do that too:

Map<String, ArrayList<Integer>> stateValues = new HashMap<String, ArrayList<Integer>>

// Unless you can affirmatively determine whether or not this key
// already exists or not, you should check before each use to make sure
// you don't accidentally use a list that isn't created yet, or 
// over-write one with data with a new empty one
if (!stateValues.containsKey("Oregon")) {
    stateValues.put("Oregon", new ArrayList<>()); // It wasn't, create,
}
stateValues.get("Oregon").add(17);
stateValues.get("Oregon").add(8);

This solution would still require you to loop through your original data. Separate the state name and the number (Probably by regex), and then put each piece of data into it's proper place.

Hope this helps!

P.S. If you tell us what version of java you're running for this, we can optimize the results to utilize the latest available features. This will compile on at least 6, and maybe 5 and is consequently more verbose than it needs to be if you were running 7 or 8.

Community
  • 1
  • 1
Julian
  • 1,665
  • 2
  • 15
  • 33
  • So i have to do it for specific names.....like add or avg all of the values under the name Utah. Would this do that? – Jay S Oct 07 '15 at 20:02
  • I made an update to the answer to try to address that a bit more. – Julian Oct 07 '15 at 21:11