I have 2 variables stored in a map as List<Object>:
int value;
int[] values;
Here, int also will be stored as Arrays.asList(value).
When we get attributesMap.get("value") --> It will be returned as List<Object>.
So, I use the following code to retrieve the value.
To get value:
(Integer)attributesMap.get("value").stream().findFirst().get();
To get values:
(int[])attributesMap.get("values").stream().findFirst().get();
Actually, only one of them will have the actual value.
The field which doesn't have an actual value will hold the default value 0, but this is not an actual value.
For example:
int value = 0;
int[] values = {1,2};
Here, values -> holding the real value and "value" can be ignored.
int value = 1;
int[] values = {0};
Here, value -> holding the real value and "values" can be ignored.
So, I need to get a final int[] array from the above two fields.
The logic I used:
int[] values = null;
if (attributesMap.get("value").stream().filter(value -> ((Integer)value > 0)).count() > 0) {
values = new int[1];
values[0] = (Integer)attributesMap.get("value").stream().filter(value -> ((Integer)value > 0)).findFirst().get();
}
else if (values == null) {
values = Arrays.stream((int[])attributesMap.get("values").stream().findFirst().get()).filter(value -> value>0).toArray();
}
The other approach,
int[] values = attributesMap.get("value").stream().filter(value -> ((Integer)value > 0)).count() > 0
? attributesMap.get("value").stream().mapToInt(val -> (int)val).toArray()
: (int[])attributesMap.get("values").stream().findFirst().get();
Is there any better approach with Java 8 without using if & else?
int value = (int) attributesMap.get("value").get(0);
int[] values = value > 0 ? new int[] { value } : (int[]) attributesMap.get("values").get(0);
Streams are overkill for this problem, there's already a method to get the first value in a list.
Related
I have a working recursive solution to a DP problem. I wish to memoize it.
Currently it depends on two states: the index i and a boolean variable true or false.
Could someone please point out how I could memoize it? Specifically, how I could initialize the memoization table (dp)?
I am confused because if I initialize the second state with false, I wouldn't be able to differentiate between the false that is due to initialization, versus the one where it is actually the value of the state.
Could someone please provide some advise?
Thanks.
To clarify further: This is how I declare the dp table right now:
vector<vector < bool > > dp;
How do I initialize the inner vector<bool>? I don't think I can set it to either true or false since I wouldn't be able to distinguish later if that is the value generated while executing (solving the problem) or the initialization value.
Edit: Adding the code:
class Solution {
public:
unordered_map<int, int> m1, m2;
vector<int> n1, n2;
vector<vector<int>> v;
int helper(int i, bool parsingNums1) {
if((parsingNums1 && i>=n1.size()) || (!parsingNums1 && i>=n2.size())) return v[i][parsingNums1]=0;
if(v[i][parsingNums1]!=-1) return v[i][parsingNums1];
int ans=0;
if(parsingNums1) {
//we are traversing path 1
//see if we can switch to path 2
if(m2.find(n1[i])!=m2.end())
ans=n1[i] + helper(m2[n1[i]]+1, false);
ans=max(ans, n1[i] + helper(i+1, true));
}
if(!parsingNums1) {
//we are traversing path 2
//see if we can switch to path 1
if(m1.find(n2[i])!=m1.end())
ans=n2[i] + helper(m1[n2[i]]+1, true);
ans=max(ans, n2[i] + helper(i+1, false));
}
return v[i][parsingNums1]=ans;
}
int maxSum(vector<int>& nums1, vector<int>& nums2) {
for(int i=0; i<nums1.size(); i++)
m1[nums1[i]]=i;
for(int i=0; i<nums2.size(); i++)
m2[nums2[i]]=i;
n1=nums1;
n2=nums2;
v.resize((nums1.size()>nums2.size()?nums1.size()+1:nums2.size()+1), vector<int>(2,-1));
return max(helper(0, true), helper(0, false))%(int)(1e9+7);
}
};
I am solving this LeetCode question: https://leetcode.com/problems/get-the-maximum-score/
There are 2 easy methods for handling this.
Declare another vector<vector < bool > > is_stored which is initialised as 0 and when dp[i][j] is calculated, mark is_stored[i][j] as 1. So when you are checking wether the particular state is being memorized, you can look into the is_stored.
Use vector< vector < int > > instead of vector< vector < bool > > and initialise -1 to every state to mark as not memorised.
Another way to store values is using
Map<String, Boolean> map = new HashMap<String, Boolean>(); // just a java version
then you can create key by appending i & j and store respective boolean value to that key. for example
String key = i + ',' + j;
// To validate if we calculated data before
if(map.containsKeys(key)) return map.get(key);
// To store/memoize values
boolean result = someDPmethod(); map.put(key, result);
In C# you can use nullable value types.
A nullable value type T? represents all values of its underlying value type T and an additional null value. For example, you can assign any of the following three values to a bool? variable: true, false, or null. An underlying value type T cannot be a nullable value type itself.
You can use null for indication of unvisited or unprocessed dp states.
you can simulate this in C++ by Initializing your dp memo to
vector<vector<bool*>> dp( m, vector<bool*>(n, nullptr) );
now you can use nullptr as an indicator for unprocessed dp states.
I was asked this question in the interview but could not solve it. Design a data structure which does the following
Inc(Key) -> Takes a key and increment its value by 1. If the key comes first time then make its value as 1.
Dec(Key) -> Takes a key and decrement its value by 1. It is given that its value is minimum 1.
Findmaxkey() -> Returns the key which has the maximum value corresponding to it. If there are multiple such keys then you can output any of them.
Findminkey() -> Returns the key which has the minimum value corresponding to it. If there are multiple such keys then you can output any of them.
You have to do all the operations in O(1) time.
Hint: The interviewer was asking me to use a dictionary(hashmap) with a doubly-linked list.
The data structure could be constructed as follows:
Store all keys that have the same count in a HashSet keys, and accompany that set with the value for count: let's call this pair of count and keys a "bucket".
For each count value for which there is at least a key, you'd have such a bucket. Put the buckets in a doubly linked list bucketList, and keep them ordered by count.
Also create a HashMap bucketsByKey that maps a key to the bucket where that key is currently stored (the key is listed in the bucket's keys set)
The FindMinKey operation is then simple: get the first bucket from bucketList, grab a key from it's keys set (no matter which), and return it. Similar for FindMaxKey.
The Inc(key) operation would perform the following steps:
Get the bucket corresponding to key from bucketsByKey
If that bucket exists, delete the key from it's keys set.
If that set happens to become empty, remove the bucket from bucketList
If the next bucket in bucketList has a count that is one more, then add the key to it's set, and update bucketsByKey so that it refers to this bucket for this key.
If the next bucket in bucketList has a different count (or there are no more buckets), then create a new bucket with the right count and key and insert it just before the earlier found bucket in bucketList -- or if no next bucket was found, just add the new one at the end.
If in step 2 there was no bucket found for this key, then assume its count was 0, and take the first bucket from bucketList and use it as the "next bucket" from step 4 onwards.
The process for Dec(key) is similar except that when the count is found to be already 1, nothing happens.
Here is an interactive snippet in JavaScript which you can run here. It uses the native Map for the HashMap, the native Set for the HashSet, and implements a doubly linked list as a circular one, where the start/end is marked by a "sentinel" node (without data).
You can press the Inc/Dec buttons for a key of your choice and monitor the output of FindMinKey and FindMaxKey, as well as a simple view on the data structure.
class Bucket {
constructor(count) {
this.keys = new Set; // keys in this hashset all have the same count:
this.count = count; // will never change. It's the unique key identifying this bucket
this.next = this; // next bucket in a doubly linked, circular list
this.prev = this; // previous bucket in the list
}
delete() { // detach this bucket from the list it is in
this.next.prev = this.prev;
this.prev.next = this.next;
this.next = this;
this.prev = this;
}
insertBefore(node) { // inject `this` into the list that `node` is in, right before it
this.next = node;
this.prev = node.prev;
this.prev.next = this;
this.next.prev = this;
}
* nextBuckets() { // iterate all following buckets until the "sentinel" bucket is encountered
for (let bucket = this.next; bucket.count; bucket = bucket.next) {
yield bucket;
}
}
}
class MinMaxMap {
constructor() {
this.bucketsByKey = new Map; // hashmap of key -> bucket
this.bucketList = new Bucket(0); // a sentinel node of a circular doubly linked list of buckets
}
inc(key) {
this.add(key, 1);
}
dec(key) {
this.add(key, -1);
}
add(key, one) {
let nextBucket, count = 1;
let bucket = this.bucketsByKey.get(key);
if (bucket === undefined) {
nextBucket = this.bucketList.next;
} else {
count = bucket.count + one;
if (count < 1) return;
bucket.keys.delete(key);
nextBucket = one === 1 ? bucket.next : bucket.prev;
if (bucket.keys.size === 0) bucket.delete(); // remove from its list
}
if (nextBucket.count !== count) {
bucket = new Bucket(count);
bucket.insertBefore(one === 1 ? nextBucket : nextBucket.next);
} else {
bucket = nextBucket;
}
bucket.keys.add(key);
this.bucketsByKey.set(key, bucket);
}
findMaxKey() {
if (this.bucketList.prev.count === 0) return null; // the list is empty
return this.bucketList.prev.keys.values().next().value; // get any key from first bucket
}
findMinKey() {
if (this.bucketList.next.count === 0) return null; // the list is empty
return this.bucketList.next.keys.values().next().value; // get any key from last bucket
}
toString() {
return JSON.stringify(Array.from(this.bucketList.nextBuckets(), ({count, keys}) => [count, ...keys]))
}
}
// I/O handling
let inpKey = document.querySelector("input");
let [btnInc, btnDec] = document.querySelectorAll("button");
let [outData, outMin, outMax] = document.querySelectorAll("span");
let minMaxMap = new MinMaxMap;
btnInc.addEventListener("click", function () {
minMaxMap.inc(inpKey.value);
refresh();
});
btnDec.addEventListener("click", function () {
minMaxMap.dec(inpKey.value);
refresh();
});
function refresh() {
outData.textContent = minMaxMap.toString();
outMin.textContent = minMaxMap.findMinKey();
outMax.textContent = minMaxMap.findMaxKey();
}
key: <input> <button>Inc</button> <button>Dec</button><br>
data structure (linked list): <span></span><br>
findMinKey = <span></span><br>
findMaxKey = <span></span>
Here is my answer, still I'm not sure that I haven't broken any of the circumstances that your interviewer had in mind.
We will keep a LinkedList where each element has the key and values it's corresponding to, and a pointer to its previous and next element and is always sorted by values. We store a pointer for every key, where it is placed in the LinkedList. Furthermore, for every new number that we see, we add two elements which are supposed to view the start and end element of each number and we will store a pointer to them. Since we are adding these extra elements at most two for each operation, it's still of O(1).
now for every operation (say increment), we can find where the element corresponding to this key is placed in the LinkedList using a dictionary (assuming dictionaries work in time complexity of O(1)) now, we find the last element in the LinkedList which has the same value (we can do it using the element corresponding to the end of that value and come one element backwards) and swap these two's pointers (it's only a simple swap, and this swap does not affect other elements) next we swap this element with it's next one for two times so that it falls in the segment of the next number (we may need to add that number as well), the last things to keep track of, is the value of minimum and maximum which has to be updated if the element which is changing is either the current minimum or maximum and there is no number with the same value (the start and end elements for that value are consecutive in the LinkedList)
Still, I think this approach can be improved.
The key is the problem only asks for dec(1) or inc(1). Therefore, the algorithm only needs to move a block forward or backward. That's a strong prior and gives a lot of information.
My tested code:
template <typename K, uint32_t N>
struct DumbStructure {
private:
const int head_ = 0, tail_ = N - 1;
std::unordered_map<K, int> dic_;
int l_[N], r_[N], min_ = -1, max_ = -1;
std::unordered_set<K> keys_[N];
void NewKey(const K &key) {
if (min_ < 0) {
// nothing on the list
l_[1] = head_;
r_[1] = tail_;
r_[head_] = 1;
l_[tail_] = 1;
min_ = max_ = 1;
} else if (min_ == 1) {
} else {
// min_ > 1
l_[1] = head_;
r_[1] = min_;
r_[head_] = 1;
l_[min_] = 1;
min_ = 1;
}
keys_[1].insert(key);
}
void MoveKey(const K &key, int from_value, int to_value) {
int prev_from_value = l_[from_value];
int succ_from_value = r_[from_value];
if (keys_[from_value].size() >= 2) {
} else {
r_[prev_from_value] = succ_from_value;
l_[succ_from_value] = prev_from_value;
if (min_ == from_value) min_ = succ_from_value;
if (max_ == from_value) max_ = prev_from_value;
}
keys_[from_value].erase(key);
if (keys_[to_value].size() >= 1) {
} else {
if (to_value > from_value) {
// move forward
l_[to_value] =
keys_[from_value].size() > 0 ? from_value : prev_from_value;
r_[to_value] = succ_from_value;
r_[l_[to_value]] = to_value;
l_[r_[to_value]] = to_value;
} else {
// move backward
l_[to_value] = prev_from_value;
r_[to_value] =
keys_[from_value].size() > 0 ? from_value : succ_from_value;
r_[l_[to_value]] = to_value;
l_[r_[to_value]] = to_value;
}
}
keys_[to_value].insert(key);
min_ = std::min(min_, to_value);
max_ = std::max(max_, to_value);
}
public:
DumbStructure() {
l_[head_] = -1;
r_[head_] = tail_;
l_[tail_] = head_;
r_[tail_] = -1;
}
void Inc(const K &key) {
if (dic_.count(key) == 0) {
dic_[key] = 1;
NewKey(key);
} else {
MoveKey(key, dic_[key], dic_[key] + 1);
dic_[key] += 1;
}
}
void Dec(const K &key) {
if (dic_.count(key) == 0 || dic_[key] == 1) {
// invalid
return;
} else {
MoveKey(key, dic_[key], dic_[key] - 1);
dic_[key] -= 1;
}
}
K GetMaxKey() const { return *keys_[max_].begin(); }
K GetMinKey() const { return *keys_[min_].begin(); }
};
I have a Stream<Set<Integer>> intSetStream.
I can do this on it...
Set<Integer> theSetWithTheMax = intSetStream.max( (x,y)->{ return Integer.compare( x.size(), y.size() ); } ).get( );
...and I get a hold of the Set<Integer> that has the highest number of Integer elements in it.
That's great. But what I really need to know is, is it the 1st Set in that Stream that's the max? Or is it the 10th Set in the Stream? Or the ith Set? Which one of them has the most elements in it?
So my question is: Is there some way — using the Stream API — that I can determine "It was the ith Set in the Stream of Sets that returned the largest value of them all, for the Set.size( ) call"?
The best solution I can think of, is to iterate over the Stream<Set<Integer>> (using intSetStream.iterator()) and do a hand-rolled max( ) calculation. But I'm hoping to learn a more Stream-y way to go about it; if there is such a thing.
You can do this with a custom collector:
int posOfMax = stream.mapToInt(Set::size)
.collect(() -> new int[] { 0, -1, -1 },
(a,i) -> { int pos = a[0]++; if(i>a[2]) { a[1] = pos; a[2] = i; } },
(a1,a2) -> {
if(a2[2] > a1[2]) { a1[1] = a1[0]+a2[1]; a1[2] = a2[2]; }
a1[0] += a2[0];
})[1];
This is the most lightweight solution. Its logic becomes clearer when we use a dedicated class instead of an array:
int posOfMax = stream.mapToInt(Set::size)
.collect(() -> new Object() { int size = 0, pos = -1, max = -1; },
(o,i) -> { int pos = o.size++; if(i>o.max) { o.pos = pos; o.max = i; } },
(a,b) -> {
if(b.max > a.max) { a.pos = a.size+b.pos; a.max = b.max; }
a.size += b.size;
}).pos;
The state object holds the size, which is simply the number of elements encountered so far, the last encountered max value and its position which we update to the previous value of the size if the current element is bigger than the max value. That’s what the accumulator function (the second argument to collect) does.
In order to support arbitrary evaluation orders, i.e. parallel stream, we have to provide a combiner function (the last argument to collect). It merges the state of two partial evaluation into the first state. If the second state’s max value is bigger, we update the first’s max value and the position, whereas we have to add the first state’s size to the second’s position to reflect the fact that both are partial results. Further, we have to update the size to the sum of both sizes.
One way to do it is to firstly map Stream<Set<Integer>> to a Collection<Integer> where each element is the size of each Set<Integer> and then you can extract what is the largest number of elements given Stream<Set<Integer>> and then get the "index" of this set by finding an index of the largest number in the collection of sizes.
Consider following example:
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class IntSetStreamExample {
public static void main(String[] args) {
final Stream<Set<Integer>> stream = Stream.of(
new HashSet<>(Arrays.asList(1,2,3)),
new HashSet<>(Arrays.asList(1,2)),
new HashSet<>(Arrays.asList(1,2,3,4,5)),
new HashSet<>(Arrays.asList(0)),
new HashSet<>(Arrays.asList(0,1,2,3,4,5)),
new HashSet<>()
);
final List<Integer> result = stream.map(Set::size).collect(Collectors.toList());
System.out.println("List of number of elements in Stream<Set<Integer>>: " + result);
final int max = Collections.max(result);
System.out.println("Largest set contains " + max + " elements");
final int index = result.indexOf(max);
System.out.println("Index of the largest set: " + index);
}
}
The exemplary output may look like this:
List of number of elements in Stream<Set<Integer>>: [3, 2, 5, 1, 6, 0]
Largest set contains 6 elements
Index of the largest set: 4
Streams methods are not designed to be aware of the current element iterated.
So I think that you actual way : find the Set with the max of elements and then iterate on the Sets to find this Set is not bad.
As alternative you could first collect the Stream<Set<Integer>> into a List (to have a way to retrieve the index) and use a SimpleImmutableEntry but it seems really overkill :
Stream<Set<Integer>> intSetStream = ...;
List<Set<Integer>> list = intSetStream.collect(Collectors.toList());
SimpleImmutableEntry<Integer, Set<Integer>> entry =
IntStream.range(0, list.size())
.mapToObj(i -> new SimpleImmutableEntry<>(i, list.get(i)))
.max((x, y) -> {
return Integer.compare(x.getValue()
.size(),
y.getValue()
.size());
})
.get();
Integer index = entry.getKey();
Set<Integer> setWithMaxNbElements = entry.getValue();
Insight provided in #Holzer's custom Collector-based solution (on top of my downright shameless plagiarizing of the source code of IntSummaryStatistics.java), inspired a custom Collector-based solution of my own; that might, in turn, inspire others...
public class IndexOfMaxCollector implements IntConsumer {
private int max = Integer.MIN_VALUE;
private int maxIdx = -1;
private int currIdx = 0;
public void accept( int value ){
if( value > max )
maxIdx = currIdx;
max = Math.max( max, value );
currIdx++;
}
public void combine( IndexOfMaxCollector other ){
if( other.max > max ){
maxIdx = other.maxIdx + currIdx;
max = other.max;
}
currIdx += other.currIdx;
}
public int getMax( ){ return this.max; }
public int getIndexOfMax( ){ return this.maxIdx; }
}
...Using that custom Collector, I could take the intSetStream of my OQ and determine the index of the Set<Integer> that contains the highest number of elements, like this...
int indexOfMax = intSetStream.map( Set::size )
.collect( IndexOfMaxCollector::new,
IndexOfMaxCollector::accept,
IndexOfMaxCollector::combine )
.getIndexOfMax( );
This solution — admittedly not the most "beautiful" — possibly has a teensie bit of an edge over others in both the reusability and understandability stakes.
Given a list of integer elements, how to get the max value and it's index in one shot. If there is more than one element with same max value, returning index of any one of them is fine.
For example:
// Initialize list of integer
List<Integer> intList = Arrays.asList(5, 8, 3, 2);
// To get max value
Optional<Integer> maxVal = intList.stream().reduce(Integer::max);
// But how could I also get its index without iterating the array again?
If I have to do it only once, I could just sort the array and get the first or last one (based on sort order). However, I would like to see how we can do it without sorting.
Generally, if you need an index, you’ll have to stream over the indices. Then, the task becomes straight-forward:
List<Integer> intArr = Arrays.asList(5, 8, 3, 2);
IntStream.range(0, intArr.size())
.reduce((a,b)->intArr.get(a)<intArr.get(b)? b: a)
.ifPresent(ix->System.out.println("Index "+ix+", value "+intArr.get(ix)));
a more elegant solution, which unfortunately incorporates boxing overhead is
IntStream.range(0, intArr.size())
.boxed().max(Comparator.comparing(intArr::get))
.ifPresent(ix->System.out.println("Index "+ix+", value "+intArr.get(ix)));
If you don't mind using third-party code, my StreamEx library provides some shortcuts for this task:
List<Integer> intArr = Arrays.asList(5, 8, 3, 2);
IntStreamEx.ofIndices(intArr)
.maxBy(intArr::get)
.ifPresent(ix->System.out.println("Index "+ix+", value "+intArr.get(ix)));
Internally it's close to the first solution provided by #Holger (no boxing).
I don't think there is currently any solution that's equally as fast as iterating manually:
int maxValueIndex = 0;
Integer maxValue = null;
for (int i = 0, n = intList.size(); i < n; ++i) {
Integer value = intList.get(i);
if (value == null || maxValue != null && value <= maxValue)
continue;
maxValue = value;
maxValueIndex = i;
}
In java8 you can execute streams in parallel
Integer[] intArr= {1,2,6,2,234,3,54,6,4564,456};
IntStream.range(0, intArr.length-1).parallel().
reduce((a,b)->intArr[a]<intArr[b]? b: a).
ifPresent(ix -> System.out.println("Index: " + ix + ", value: " + intArr[ix]));
A machine is taking measurements and giving me discrete numbers continuously like so:
1 2 5 7 8 10 11 12 13 14 18
Let us say these measurements can be off by 2 points and a measurement is generated every 5 seconds. I want to ignore the measurements that may potentially be same
Like continuous 2 and 3 could be same because margin of error is 2 so how do I partition the data such that I get only distinct measurements but I would also want to handle the situation in which the measurements are continuously increasing like so:
1 2 3 4 5 6 7 8 9 10
In this case if we keep ignoring the consecutive numbers with difference of less than 2 then we might lose actual measurements.
Is there a class of algorithms for this? How would you solve this?
Just drop any number that comes 'in range of' the previous (kept) one. It should simply work.
For your increasing example:
1 is kept, 2 is dropped because it is in range of 1, 3 is dropped because it is in range of 1, then 4 is kept, 5 and 6 are dropped in range of 4, then 7 is kept, etc, so you still keep the increasing trend if it's big enough (which is what you want, right?
For the original example, you'd get 1,5,8,11,14,18 as a result.
In some lines of work, the standard way to deal with problems of this nature is by using the Kalman filter.
To quote Wikipedia:
Its [Kalman filter's] purpose is to use measurements
observed over time, containing noise
(random variations) and other
inaccuracies, and produce values that
tend to be closer to the true values
of the measurements and their
associated calculated values.
The filter itself is very easy to implement, but does require calibration.
I would have two queues:
Temporary Queue
Final Queue/List
Your first value would go into the temporary queue and in the final list. As new values come in, check to see if the new value is within the deadband of the last value in the list. If it is then add it to the temporary queue. If not then add it to the final list. If your temporary queue starts to increase in size before you get a new value outside of the deadband, then once you are outside of the deadband do a check to see if the values are monotonically increasing or decreasing the whole time. If they are always increasing or decreasing then add the contents of the queue to the final list, otherwise just add the single new value to the final list. This is the general gist of it.
Here is some code I whipped up quickly that implements a class to do what I described above:
public class MeasurementsFilter
{
private Queue<int> tempQueue = new Queue<int>();
private List<int> finalList = new List<int>();
private int deadband;
public MeasurementsFilter(int deadband)
{
this.deadband = deadband;
}
public void Reset()
{
finalList.Clear();
tempQueue.Clear();
}
public int[] FinalValues()
{
return finalList.ToArray();
}
public void AddNewValue(int value)
{
// if we are just starting then the first value always goes in the list and queue
if (tempQueue.Count == 0)
{
tempQueue.Enqueue(value);
finalList.Add(value);
}
else
{
// if the new value is within the deadband of the last value added to the final list
// then enqueue the value and wait
if ((tempQueue.Peek() - deadband <= value) && (value <= tempQueue.Peek() + deadband))
{
tempQueue.Enqueue(value);
}
// else the new value is outside of the deadband of the last value added to the final list
else
{
tempQueue.Enqueue(value);
if (QueueIsAlwaysIncreasingOrAlwaysDecreasing())
{
//dequeue first item (we already added it to the list before, but we need it for comparison purposes)
int currentItem = tempQueue.Dequeue();
while (tempQueue.Count > 0)
{
// if we are not seeing two in a row of the same (i.e. they are not duplicates of each other)
// then add the newest value to the final list
if (currentItem != tempQueue.Peek())
{
currentItem = tempQueue.Dequeue();
finalList.Add(currentItem);
}
// otherwise if we are seeing two in a row (i.e. duplicates)
// then discard the value and loop to the next value
else
{
currentItem = tempQueue.Dequeue();
}
}
// add the last item from the final list back into the queue for future deadband comparisons
tempQueue.Enqueue(finalList[finalList.Count - 1]);
}
else
{
// clear the queue and add the new value to the list and as the starting point of the queue
// for future deadband comparisons
tempQueue.Clear();
tempQueue.Enqueue(value);
finalList.Add(value);
}
}
}
}
private bool QueueIsAlwaysIncreasingOrAlwaysDecreasing()
{
List<int> queueList = new List<int>(tempQueue);
bool alwaysIncreasing = true;
bool alwaysDecreasing = true;
int tempIncreasing = int.MinValue;
int tempDecreasing = int.MaxValue;
int i = 0;
while ((alwaysIncreasing || alwaysDecreasing) && (i < queueList.Count))
{
if (queueList[i] >= tempIncreasing)
tempIncreasing = queueList[i];
else
alwaysIncreasing = false;
if (queueList[i] <= tempDecreasing)
tempDecreasing = queueList[i];
else
alwaysDecreasing = false;
i++;
}
return (alwaysIncreasing || alwaysDecreasing);
}
}
Here is some test code that you can throw into a Winform Load event or button click:
int[] values = new int[] { 1, 2, 2, 1, 4, 8, 3, 2, 1, 0, 6 };
MeasurementsFilter filter = new MeasurementsFilter(2);
for (int i = 0; i < values.Length; i++)
{
filter.AddNewValue(values[i]);
}
int[] finalValues = filter.FinalValues();
StringBuilder printValues = new StringBuilder();
for (int i = 0; i < finalValues.Length; i++)
{
printValues.Append(finalValues[i]);
printValues.Append(" ");
}
MessageBox.Show("The final values are: " + printValues);