Генерация ценовых диапазонов в Java из Big-Integer-List

У меня есть список продуктов, которые имеют цену как BigInteger. Я хочу создать динамические ценовые диапазоны для фильтрации поиска товаров, как это делает Google на google.com/shopping:

динамические ценовые диапазоны от Google Покупки

Как рассчитать хорошие динамические ценовые диапазоны из заданного списка товаров / цен? Я попробовал Google, но не смог найти хорошие результаты или решения вообще! Я не хочу определять диапазоны вручную и просто добавлять цены к заданным диапазонам....

Я ценю вашу помощь!

1 ответ

Решение

Вы должны отфильтровать ваши продукты, например, с помощью Java 8 Streaming API (если доступна Java 8):

List<Product> results = new ArrayList();    
products.stream().filter(p -> p.getPrice() > minPrice && p.getPrice() < maxPrice).forEach(results::add);

Конечно, в конце потока вы могли бы сделать .forEach(this::output); вместо.

Если вам нужна поддержка для более старых версий, эквивалент будет for цикл:

for(Product p : products){
   if(p.getPrice() > minPrice && p.getPrice() < maxPrice)
      this.output(p); //or add to a list
}

Вы можете конечно обернуть это как метод:

public static List<Product> filterProducts(BigInteger minPrice, BigInteger maxPrice){
   List<Product> results = new ArrayList();    
   products.stream().filter(p -> p.getPrice() > minPrice && p.getPrice() < maxPrice).forEach(results::add);
   return results;
}

Найти диапазоны

Если у вас есть 30 предметов, которые вы хотите разделить на 3 диапазона, вы хотите, чтобы ваши диапазоны были ценой наименьшего - где-то между ценой десятого наименьшего и ценой одиннадцатого наименьшего.

давайте предположим, что вы уже отсортировали свой список как-то:

double[] calcRanges(List<Product> sortedProducts, int count){
    double result = new double[count + 1];
    result[0] = 0;
    for(int i = 1; i < result.length; i++) {
        int pos = (sortedProducts.getSize() * i) / count;
        result[i] = sortedProducts.get(pos).getPrice();
    }
}

Проблема в том, что вы получите диапазоны, такие как 2.99 - 3.49 / 3.49 - 12.35 и т. Д.

Это означает, что вам нужно будет "округлить" цены. Вы можете создать статический список допустимых диапазонов начала и конца диапазона и найти следующий по величине конец диапазона:

double[] allowedRangeEnds = {0,1,5,10,20,50,100,200,500,1000,2000,5000,10000};

//returns the smalles allowed rangeend which is > value
double getNextRangeEnd(double value){
    int i = 0;
    while(allowedRangeEnds[i] < value && i < allowedRangeEnds.length - 1){
        i++;
    }
    return allowedRangeEnds[i];
}

Конечно, вы можете сгенерировать свои диапазоны, если ваши цены взлетят, и вы не захотите менять свои статические диапазоны:

List<Double> calcRangeEnds(double maxValue) {
    List<Double> result = new ArrayList<Double>();
    double base = 1;
    while(base / 2 <= maxValue) { //the last value added is base / 2
        result.add(base);
        result.add(base * 2);
        result.add(base * 5);
        base *= 10;
    }
    return result;
}
Другие вопросы по тегам