[英]Find the lowest and highest NUMBERS in a collection
I have a List<BigDecimal>
collection which contains (for the sake of simplicity) BigDecimal
prices.我有一个
List<BigDecimal>
集合,其中包含(为了简单起见) BigDecimal
价格。 I would like to process the collection and get:我想处理集合并得到:
My initial thoughts are to approach this using look-behind in order to decide if the numbers are moving in an up or down trend.我最初的想法是使用后视法来解决这个问题,以确定数字是在上升还是下降趋势中移动。 When the trend changes - determine which of the previous numbers are "highest" or "lowest" prices and then add them to the respectful
List<BigDecimal> lowestPrices
and List<BigDecimal highestPrices
collections. For example, the first 3 dots are in an up-trend, but the 4th changes the trend to a down-trend.当趋势发生变化时——确定之前的数字中哪些是“最高”或“最低”价格,然后将它们添加到尊重的
List<BigDecimal> lowestPrices
和List<BigDecimal highestPrices
collections。例如,前 3 个点是向上的-trend,但是 4 号将趋势变为下降趋势。 So can now determine the min/max
of the numbers before the change (0,1,2) and get the prices.所以现在可以确定更改前数字的
min/max
(0,1,2) 并获取价格。
I am not entirely sure if this isn't a naive approach so I was wondering if there would be the best approach to solving this issue in java?我不完全确定这是否是一种幼稚的方法,所以我想知道 java 中是否有解决此问题的最佳方法? Maybe a library that can already do this?
也许图书馆已经可以做到这一点? (probably better not to re-invent the wheel)
(最好不要重新发明轮子)
You are looking for local maxima (/minima).您正在寻找局部最大值(/最小值)。
Just look at whether the current point is greater (/less) than the point preceding and following it:只需查看当前点是否大于(/小于)其前后的点:
For a local maximum:对于局部最大值:
list.get(i) > list.get(i - 1) && list.get(i) > list.get(i + 1)
For a local minimum:对于局部最小值:
list.get(i) < list.get(i - 1) && list.get(i) < list.get(i + 1)
Pseudocode:伪代码:
for (int i = 1; i < list.size()-1; ++i) {
if (local maximum) {
// Add to list of local maxima
} else if (local minimum) {
// Add to list of local minima
}
}
and handle the two endpoints as you desire.并根据需要处理这两个端点。
(You can also do this in ways that are more efficient for non-random access lists, eg LinkedList
, using (List)Iterators; but the principle is the same). (您也可以使用 (List)Iterators 以对非随机访问列表更有效的方式执行此操作,例如
LinkedList
;但原理是相同的)。
I decided to try implementing this, although I'm sure my implementation could be improved.我决定尝试实现这一点,尽管我确信我的实现可以改进。 The idea is just as you say, to keep track of the trend and record a local minimum or local maximum whenever the trend changes.
这个想法就像你说的那样,跟踪趋势并在趋势发生变化时记录局部最小值或局部最大值。 There are two additional details to consider: first, initially we are not trending up or down, but the first value is either a minimum or maximum, so we have a third possibility for the trend, in addition to increasing or decreasing: inchoate;
还有两个额外的细节需要考虑:首先,最初我们没有趋势向上或向下,但第一个值是最小值或最大值,因此除了增加或减少之外,我们还有第三种趋势可能性:早期; second, after the end of the loop we have to add the last item as either a minimum or maximum, depending on the direction the trend was going when we finished.
其次,在循环结束后,我们必须添加最后一项作为最小值或最大值,具体取决于我们完成时趋势的方向。 Note that it will never add null if the list of prices is empty, because in that case, the trend would never have changed from inchoate.
请注意,如果价格列表为空,它永远不会添加 null,因为在这种情况下,趋势永远不会从早期发生变化。
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Map;
import java.util.List;
public class Partition {
public static void main(String[] args) {
List<String> values = List.of("10.99", "15.99", "19.99", "12.99", "24.99",
"21.99", "17.99", "11.99", "22.99", "29.99", "35.99", "27.99", "20.99");
List<BigDecimal> prices = values.stream().map(BigDecimal::new).toList();
Map<Extrema, List<BigDecimal>> part = new Partition().partitionExtrema(prices);
System.out.format("Minima: %s%n", part.get(Extrema.MINIMA));
System.out.format("Maxima: %s%n", part.get(Extrema.MAXIMA));
}
public Map<Extrema, List<BigDecimal>> partitionExtrema(List<BigDecimal> prices) {
Trend trend = Trend.INCHOATE; // intially we don't know if we're going up or down
List<BigDecimal> maxima = new ArrayList<>();
List<BigDecimal> minima = new ArrayList<>();
BigDecimal previous = null;
for (BigDecimal current : prices) {
int direction = previous == null ? 0 : current.compareTo(previous);
if (direction > 0) {
if (trend != Trend.DECREASING) {
minima.add(previous); // switching from decreasing to increasing
}
trend = Trend.INCREASING;
}
if (direction < 0) {
if (trend != Trend.INCREASING) {
maxima.add(previous); // switching from increasing to decreasing
}
trend = Trend.DECREASING;
}
previous = current;
}
if (trend == trend.INCREASING) {
maxima.add(previous);
} else if (trend == trend.DECREASING) {
minima.add(previous);
}
return Map.of(Extrema.MINIMA, minima, Extrema.MAXIMA, maxima);
}
}
public enum Trend {
INCREASING,
DECREASING,
INCHOATE
}
public enum Extrema {
MAXIMA,
MINIMA
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.