As said in this previous question, I am using the Reactive library in a C# project to group incoming data according to pre-configured policies. All these data implement the following interface:
public interface IPoint
{
object Value { get; }
DateTimeOffset Timestamp { get; }
}
My goal is to implement a "hopping" buffer based on the Timestamps of the received data (both buffer size and hop/shift size are declared at the beginning as TimeSpans). Hop/shift size can be less than the buffer size, which means that some IPoint instances can belong to more than one group.
An example: considering the following IPoint
Value: 1, Timestamp: "2021-05-25T00:00:01"
Value: 2, Timestamp: "2021-05-25T00:00:02"
Value: 3, Timestamp: "2021-05-25T00:00:03"
Value: 4, Timestamp: "2021-05-25T00:00:04"
Value: 5, Timestamp: "2021-05-25T00:00:05"
with a buffer size of 3 seconds and a hop/shift size of 2 seconds, I am expecting them to be grouped as [1, 2, 3], [3, 4, 5].
with a buffer size of 2 seconds and a hop/shift size of 3 seconds, I am expecting them to be grouped as [1, 2], [4, 5]
I've seen that there is a Buffer(timeSpan, timeShift) extension doing this job, but it considers a runtime-calculated timestamp instead of the ones of the passed IPoints.
I've tried to look for a solution, but I couldn't find anything helpful.
I am a newbie at Reactive, so any helpful comment is welcome (also for the other question). Thank you.
Edit: as in the previous question, I am using an ISubject<IPoint> in this way:
ISubject<IPoint> subject = new Subject<IPoint>();
// ...
// when new data come from an external source
public void Add(IPoint newPoint)
{
subject.OnNext(newPoint);
}
// subscription made by another class in order to be called when "hopping" buffer is ready
public void Subscribe(Action<IEnumerable<IPoint>> callback)
{
// TODO: implement buffer + .Subscribe(callback)
}
Related
I am using Reactive library in my C# project to group data according to configured policies. All these data implement the following interface
public interface IPoint
{
object Value { get; }
DateTimeOffset Timestamp { get; }
}
One of the grouping policies I have to implement consists creating non-overlappable groups of a fixed time size, which looking at Reactive documentation could be achieved using Buffer(TimeSpan) function. This is exactly what I need, but instead of using a runtime calculated timestamp I need to use the ones defined in the Timestamp property of my objects.
I found this solution, which seems quite working:
public void Subscribe(Action<IEnumerable<IPoint>> callback)
{
long windowSizeTicks = TimeRange.Ticks; // TimeRange is my TimeSpan "buffer" size
dataPoints.GroupByUntil(x => x.Timestamp.Ticks / windowSizeTicks,
g => dataPoints.Where(x => x.Timestamp.Ticks / windowSizeTicks != g.Key))
.SelectMany(x => x.ToList())
.Subscribe(callback);
// dataPoints is ISubject<IPoint>
}
This solution just creates groups according to Ticks divisibility by TimeRange, which doesn't work correctly if the first item is not divisible by it.
An example to explain what I mean: considering the following points
Value: 1, Timestamp: "2021-04-26T00:00:01"
Value: 2, Timestamp: "2021-04-26T00:00:02"
Value: 3, Timestamp: "2021-04-26T00:00:03"
Value: 4, Timestamp: "2021-04-26T00:00:04"
and a "buffer size" of 2 seconds, I am expecting them to be grouped as [1, 2], [3, 4], but instead I receive [1], [2, 3], [4]. This happens because the grouping key is created considering the absolute time and not the difference from the starting of the data list.
I could save the timestamp of the first item and change the grouping function in this way, but I think (or at least I hope) there could be a better solution:
public void Subscribe(Action<IEnumerable<IPoint>> callback)
{
long windowSizeTicks = TimeRange.Ticks; // TimeRange is my TimeSpan "buffer" size
dataPoints.GroupByUntil(x => (x.Timestamp.Ticks - firstPoint.Timestamp.Ticks) / windowSizeTicks,
g => dataPoints.Where(x => (x.Timestamp.Ticks - firstPoint.Timestamp.Ticks) / windowSizeTicks != g.Key))
.SelectMany(x => x.ToList())
.Subscribe(callback);
// dataPoints is ISubject<IPoint>
}
I am a newbie at Reactive, so any helpful comment is welcome.
Thank you.
I came from C# world, and used to arrays being reference types. As I understand, in swift arrays are value types, but they try to play as reference ones.
I don't actually know how to ask what I need (I think this is the case when I need to know answer to be able to ask question), but in C# I would say I need to store a reference to inner array of a jagged array into local variable.
Consider the following piece of code:
// a function to change row values in-place
func processRow(inout row : [Int], _ value : Int)
{
for col in 0..<row.count
{
row[col] = value;
}
}
// a function to change matrix values in-place
func processMatrix(inout matrix : [[Int]])
{
for rowIdx in 0..<matrix.count
{
// (1) Works with array in-place
processRow(&(matrix[rowIdx]), -1)
// (2) Creates local copy
var r = matrix[rowIdx]; // <--- What to write here to not make a copy but still have this local variable?
processRow(&r, -2);
}
}
var matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
processMatrix(&matrix)
print(matrix) // outputs [[-1, -1, -1], [-1, -1, -1], [-1, -1, -1]]
Swift sandbox here http://swiftlang.ng.bluemix.net/#/repl/8608824e18317e19b32113e1aa08deeb4ec5ab96ed8cdbe1dbfb4e753e87d528
Here I want to I process multidimensional array in-place, so that I don't create a copy of array or parts of array.
In option (1) I change everything to "-1", and it works, but is uses additional function for this.
In option (2) I try to use local variable to store matrix[rowIdx], but it actually creates a copy of inner array - not what I want; working with this variable changes copy of array, and not original one.
How can I achieve results like in option (1), but using local variable instead of function? That is, how can I obtain reference to inner array and put it to local variable?
I would understand answer "there's no way for this", but I want such answers to be accompanied by some Apple refs.
I don't believe that there is a way to copy an array into a local variable without making a copy. That is just the way that value types work in Swift. Says Apple:
The most basic distinguishing feature of a value type is that copying — the effect of assignment, initialization, and argument passing — creates an independent instance with its own unique copy of its data[.]
And here:
A value type is a type whose value is copied when it is assigned to a variable or constant, or when it is passed to a function...
[...]
All structures and enumerations are value types in Swift. This means that any structure and enumeration instances you create—and any value types they have as properties—are always copied when they are passed around in your code.
It's just part of the definition of value type - and every array is a value type.
The easiest way to get the result you are seeking is simply to reassign the value of r to the row that you want to change in matrix:
// (2) Creates local copy
var r = matrix[rowIdx]
processRow(&r, -2)
matrix[rowIdx] = r
The closest thing to what you are suggesting is to work with pointers: UnsafeMutablePointer, UnsafePointer, etc. But that is really fighting against the way that Swift was designed to be used. If you wanted to, however, it would look something like this:
func processRow(ptr: UnsafeMutablePointer<Int>, _ value : Int, count: Int) {
for col in 0..<count {
ptr.advancedBy(col).memory = value
}
}
func processMatrix(inout matrix : [[Int]]) {
for rowIdx in 0..<matrix.count {
let r = UnsafeMutablePointer<Int>(matrix[rowIdx])
processRow(r, -2, count: matrix[rowIdx].count)
}
}
var matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
processMatrix(&matrix)
print(matrix) // [[2, 2, 2], [2, 2, 2], [2, 2, 2]]
Swift arrays are pretty painful when it comes to work with mutable data. There are two ways to fix that:
1) Use NSMutableArray
import Foundation
func processRow(_ row : NSMutableArray, _ value : Int) {
for col in 0..<row.count {
row[col] = value;
}
}
func processMatrix(_ matrix : inout [NSMutableArray]) {
for rowIdx in 0..<matrix.count {
let r = matrix[rowIdx]
processRow(r, -2);
}
}
var matrix = [
NSMutableArray(array: [1, 2, 3]),
NSMutableArray(array: [4, 5, 6]),
NSMutableArray(array: [7, 8, 9])
]
processMatrix(&matrix)
print(matrix) // outputs , <__NSArrayM 0x6000027a1560>(-2,-2,-2)]
2) Use class wrapper
class Wrapper<T: CustomDebugStringConvertible>: CustomDebugStringConvertible {
var value: T
init(_ value: T) {
self.value = value
}
var debugDescription: String {
return value.debugDescription
}
}
func processRow(_ row : Wrapper<[Int]>, _ value : Int) {
for col in 0..<row.value.count {
row.value[col] = value;
}
}
func processMatrix(_ matrix : inout [Wrapper<[Int]>]) {
for rowIdx in 0..<matrix.count {
let r = matrix[rowIdx]
processRow(r, -2);
}
}
var matrix = [
Wrapper([1, 2, 3]),
Wrapper([4, 5, 6]),
Wrapper([7, 8, 9])
]
processMatrix(&matrix)
print(matrix) // outputs [[-2, -2, -2], [-2, -2, -2], [-2, -2, -2]]
However it doesn't look very nice.
We have an interesting problem we need to resolve here, we're using C# .NET 4.0 but the language should be irrelevant as it's a mathematical problem.
Problem: we need to identify gaps in N dimensional data set and report exactly where those gaps are back to the user.
For example, let's assume we're working with 3-D, so we have this object Quote with 6 properties: TermFrom, TermTo, AgeFrom, AgetTo, AmountFrom, AmountTo and boundaries we need to cover: MinTerm = 0, MaxTerm = 5, MinAge = 0, MaxAge = 5, MinAmount = 0, MaxAmount = 5. Assuming all minimums are 0 and maximums are 5 just to simplify the example, albeit they could be different. So, the data we need to check for gaps in is the following data set:
Quote[] {
{ TermFrom=0, TermTo=3, AgeFrom=0, AgetTo=4, AmountFrom=0, AmountTo=2 },
{ TermFrom=4, TermTo=5, AgeFrom=0, AgetTo=5, AmountFrom=3, AmountTo=5 }
This dataset contains gaps for combinations: { Term: 0-5, Age: 4-5, Amount: 0-2 } and { Term: 0-3, Age: 0-5, Amount: 2-5 }, { Term: 4-5, Age: 0-5, Amount: 0-2 } (i think)
i.e. if you imagine a cube and the datasets are parts of this cube, to calculated total volume of all datasets must be equal to the cube's volume. And we need to identify where the gaps are in this cube if its volume isn't full.
All of this is required with more dimensions: 4 and 5, but it's a lot harder to visualise. I was hoping there is some sort of mathematical solution to this problem, which we could translate to c# code.
Use a k-d tree, it is meant precisely to partition space for these sorts of applications.
I have one data source like -4,-3,-3,-2,-1,0,1,2,2,3,4 , I have one function and this function can capture repeated number for example in this data source we have -3,2 are repeated .The repeated numbers are reported in end of the program.
I couldn't find good example(I spent 3 hours).
How can I implement a unit test with NUnit that can be test the same situation and it tells me the results, if you have some example , It will be very useful to me.(Really appreciated).
You can use TestCase attributes for simple data like what you've described.
[Test]
[TestCase(new[] { -4, -3, -3, -2, -1, 0, 1, 2, 2, 3, 4 }, new []{-3,2})]
public void YourTest(int[] given, int[] expected)
{ ... }
Note: ReSharper (at least my version of it) doesn't honor multiple test cases like this one so I had to confirm multiple test cases with the NUnit GUI.
First things first - get a working test. Something like this:
[Test]
public void DetectsMinusThreeAndTwo()
{
RepeatingDigitsDetector target = new RepeatingDigitsDetector();
int[] source = new int[] { -4, -3, -3, -2, -1, 0, 1, 2, 2, 3, 4 };
int[] expected = new int[] { -3, -2 };
int[] actual = target.GetRepeats(source);
Assert.AreEqual(expected.Length, actual.Length, "checking lengths");
for (int i = 0; i < expected.Length; i++)
{
Assert.AreEqual(expected[i], actual[i], "checking element {0}", i);
}
}
Later, you can start adding in goodies like the TestCase or TestCaseSource attributes. But if you're trying to do TDD (as the tdd tag implies), you need to start with a test.
I would recommend TestCaseSource in this instance. Several tests could make the data harder to read inside the TestCase attribute.
As your test data gets complex, it will be difficult to handle.
Consider storing your data in another source such as excel, json or Database.
I personally like storing test data in embedded json files.
The package JsonSectionReader provides good support for this.
My goal is to perform a binary search for only the first element in a 2D array. I have been searching all day to find if it is possible using BinarySearch() in .NET but I can't find a thing.
To make this clearer. Imagine I had a 1D array, unsorted. If I sort the array, I lose the original index. I would like to create a second element of my array to hold the original index (this I can do) then sort by first element, then binary search over the first elements.
If anyone could push me in the right direction I'd be very grateful.
Thanks
Well, if I understand you correctly, you need something like this:
// initialize the array and the indexes array
var a2D = new int[2][];
a2D[0] = new[] { 3, 14, 15, 92, 65, 35 }; // <-- your array (fake data here)
a2D[1] = Enumerable.Range(0, a2D[0].Length).ToArray(); // create the indexes row
// sort the first row and the second one containing the indexes
Array.Sort(a2D[0], a2D[1]);
// now a2D array contains:
// row 0: 3, 14, 15, 35, 65, 92
// row 1: 0, 1, 2, 5, 4, 3
// and you can perform binary search on the first row:
int columnIndexOf35 = Array.BinarySearch(a2D[0], 35);
// columnIndexOf35 = 3
//
// a2D[0][columnIndexOf35] = 35 <- value
// a2D[1][columnIndexOf35] = 5 <- original index
As per MSDN, Array.BinarySearch method operates only with one-dimensional arrays, so it is impossible to use it directly in your case. Some of the options you have are:
Extract first column into a separate array and call Array.BinarySearch on it.
Define custom class Pair that implements interface IComparable and construct your array with the instances of this class.
Implement binary search on two dimensional array by yourself.
It looks like you want to have object that holds data and "original index" and than sort/search array of objects by data.
(This answer shows Andrei's option 2)
class IndexedData:IComparable
{
public MyType Data;
public int OriginalIndex;
public int CompareTo(object obj) {
// add correct checks for null,.. here
// and return correct comparison result.
// I.e. if MyType is IComparable - just delegate.
return Data.CompareTo(obj);
}
Check IComparable on MSDN for implementation/usage details.
Depending on what you're planning to do with the arrays afterwards, another solution might be to use LINQ.
var unsortedStartingArray = new[] {3, 6, 2, 1, 20, 20};
var q = unsortedStartingArray
.Select((item, index) => new {item, index})
.ToLookup(x => x.item, x => x.index);
var notFound = q[30]; // An empty array. Nothing found
var indexOf1 = q[1].First(); // returns 3
var multipleIndexsOf20 = q[20]; // Returns an array with 4, 5
The index into the lookup would then be the value you're searching for. Performance wise I would guesstimate this to be faster aswell about 5 times slower from my crude testing.