开发者

Java: Generating distribution of values in an ArrayList

开发者 https://www.devze.com 2023-02-15 00:42 出处:网络
I have a sorted ArrayList of values. I would like to get the distribution of the values. For example:

I have a sorted ArrayList of values. I would like to get the distribution of the values. For example:

  • Say I have 500 values, ranging from 1-100.
  • I want to break them up into groups, say 10 groups: values 1-10, 11-20, 21-30, etc...
  • I want the counts of each of the 500 values that fall into each category开发者_JAVA百科. For example, 5 of the 500 are valued at 1-10, 20 between 11-20, etc...
  • However, I do not know the ranges of values in my ArrayList, it could be ranging from 1-30 or 1-200, but I want to break it up into, for example, 10 groups.

Does anyone know how to do this?


Using Guava gets you pretty far in that direction. Here's some code to get you started:

// initialize the List with 500 random values between 1 and 200
// you'll probably supply your existing lists instead
final Random rand = new Random();
final List<Integer> list = new ArrayList<Integer>();
for(int i = 0; i < 500; i++){
    list.add(rand.nextInt(200)+1);
}

// create a multiset
final Multiset<Integer> multiset = TreeMultiset.create(list);

// create 10 partitions of entries
// (each element value may appear multiple times in the multiset
// but only once per partition)
final Iterable<List<Integer>> partitions =
    Iterables.partition(
        multiset.elementSet(),
        // other than aioobe, I create the partition size from
        // the number of unique entries, accounting for gaps in the list
        multiset.elementSet().size() / 9
    );

int partitionIndex = 0;
for(final List<Integer> partition : partitions){

    // count the items in this partition
    int count = 0;
    for(final Integer item : partition){
        count += multiset.count(item);
    }
    System.out.println("Partition " + ++partitionIndex + " contains "
            + count + " items (" + partition.size() + " unique) from "
            + partition.get(0) + " to "
            + partition.get(partition.size() - 1));
}

Output:

Partition 1 contains 53 items (20 unique) from 1 to 21
Partition 2 contains 49 items (20 unique) from 22 to 42
Partition 3 contains 58 items (20 unique) from 43 to 63
Partition 4 contains 60 items (20 unique) from 64 to 84
Partition 5 contains 58 items (20 unique) from 85 to 104
Partition 6 contains 44 items (20 unique) from 105 to 126
Partition 7 contains 46 items (20 unique) from 127 to 146
Partition 8 contains 54 items (20 unique) from 147 to 170
Partition 9 contains 50 items (20 unique) from 171 to 191
Partition 10 contains 28 items (8 unique) from 192 to 200

Reference:

  • TreeMultiset
  • Iterables.partition(iterable, size)


I do not know the ranges of values in my ArrayList, it could be ranging from 1-30 or 1-200, but I want to break it up into, for example, 10 groups.

To find out the sizes of the groups, you take the maximum value (the last value since the array is sorted) minus the minimum value (the first value) and divide it by the number of groups you want (and round it up to the closest integer).

So, in your example, if you have a list ranging from 1-30 and want to get it in 10 groups, you'll have a group size of

N = ceil((30 - 1) / 10) = 3

Similarly, if the list ranged from 1-200, you'd get

N = ceil((200 - 1) / 10) = 20

You then compute the i:th group, counting from 0, as N×i - (N+1)×i-1

To actually get hold of the lists for these groups, you step through the list and look for the "boundaries" and break up the list using ArrayList.sublist(start, end).


As an alternative to @sean-patrick-floyd's answer you can also use Guava's Multimaps.index to apply a function to each item in the list and assign it to a group:

//generate a sorted list of 500 items between 1..100
final Random rand = new Random();
final List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < 500; i++) {
    list.add(rand.nextInt(100) + 1);
}
Collections.sort(list);

//////////////////////////

//specify how big you want each group to be
final int groupRange = 10;

//create a multimap
ListMultimap<Integer, Integer> map = Multimaps.index(list, new Function<Integer, Integer>() {
    public Integer apply(Integer i) {
        //work out which group the value belongs in
        return (i / groupRange) + (i % groupRange == 0 ? 0 : 1);
    }
});

/////////////////////////

//print it out for diagnosis
for (Integer key : map.keySet()) {
    List<Integer> value = map.get(key);
    System.out.println("Partition " + key + " contains " + value.size() + " items from " + value.get(0) + " to " + value.get(value.size() - 1));
}

Output:

Partition 1 contains 54 items from 1 to 10
Partition 2 contains 59 items from 11 to 20
Partition 3 contains 43 items from 21 to 30
Partition 4 contains 58 items from 31 to 40
Partition 5 contains 50 items from 41 to 50
Partition 6 contains 49 items from 51 to 60
Partition 7 contains 43 items from 61 to 70
Partition 8 contains 51 items from 71 to 80
Partition 9 contains 45 items from 81 to 90
Partition 10 contains 48 items from 91 to 100

Reference:

  • Multimaps
0

精彩评论

暂无评论...
验证码 换一张
取 消