Java: генерация распределения значений в ArrayList - PullRequest
2 голосов
/ 04 марта 2011

У меня есть отсортированный ArrayList значений. Я хотел бы получить распределение ценностей. Например:

  • Допустим, у меня есть 500 значений в диапазоне от 1 до 100.
  • Я хочу разбить их на группы, скажем, 10 групп: значения 1-10, 11-20, 21-30 и т. Д. *
  • Я хочу подсчет каждого из 500 значений, которые попадают в каждую категорию. Например, 5 из 500 оцениваются в 1-10, 20 между 11-20 и т. Д.
  • Однако я не знаю диапазонов значений в моем ArrayList, он может быть в диапазоне 1-30 или 1-200, но я хочу разбить его, например, на 10 групп.

Кто-нибудь знает, как это сделать?

Ответы [ 3 ]

1 голос
/ 04 марта 2011

Использование Гуава делает вас довольно далеко в этом направлении. Вот код, с которого можно начать:

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

Выход:

Раздел 1 содержит 53 элемента (20 уникальных) от 1 до 21
Раздел 2 содержит 49 предметов (20 уникальных) от 22 до 42
Раздел 3 содержит 58 предметов (20 уникальных) от 43 до 63
Раздел 4 содержит 60 предметов (20 уникальных) от 64 до 84
Раздел 5 содержит 58 предметов (20 уникальных) от 85 до 104
Раздел 6 содержит 44 предмета (20 уникальных) от 105 до 126
Раздел 7 содержит 46 предметов (20 уникальных) от 127 до 146
Раздел 8 содержит 54 предмета (20 уникальных) от 147 до 170
Раздел 9 содержит 50 предметов (20 уникальных) от 171 до 191
Раздел 10 содержит 28 предметов (8 уникальных) от 192 до 200

Справка:

1 голос
/ 04 марта 2011

Я не знаю диапазоны значений в моем ArrayList, они могут быть в диапазоне 1-30 или 1-200, но я хочу разбить его, например, на 10 групп.

Чтобы узнать размеры групп, вы берете максимальное значение (последнее значение с момента сортировки массива) минус минимальное значение (первое значение) и делите его на количество групп, которое вы хотите (и округлите его). до ближайшего целого числа).

Итак, в вашем примере, если у вас есть список в диапазоне от 1 до 30 и вы хотите получить его в 10 группах, у вас будет размер группы

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

Точно так же, если бы список составлял 1-200, вы бы получили

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

Затем вы вычисляете i : th-группу, считая от 0, как N & times; i - (N + 1) & times; i-1

Чтобы фактически получить списки для этих групп, вы шагаете по списку, ищите «границы» и разбиваете список, используя ArrayList.sublist(start, end).

0 голосов
/ 04 марта 2011

В качестве альтернативы ответу @ sean-patrick-floyd вы также можете использовать Guava's Multimaps.index , чтобы применить функцию к каждому элементу в спискеи назначить его группе:

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

Выход:

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

Ссылка:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...