I recently designed a data structure similar to 'Queue' and 'Stack' for a special purpose, with a fixed maximum number of objects in it and when it is full and inserted, the first inserted object drops out.
The Code:
public class AssemblyLine<T>
{
private long length;
public long Length { get { return this.length; } }
private T[] data;
private long Pointer = 0;
private long count = 0;
public long Count { get { return this.count; } }
public void Insert(T obj)
{
this.Data[Pointer] = obj;
this.Next();
if (this.count < this.length)
this.count++;
}
public T[] GetLastX(long x)
{
long p = this.Pointer;
if (x > this.count)
x = this.count;
T[] result = new T[x];
for (int i = 0; i < x; i++)
{
Previous();
result[i] = Grab();
}
this.Pointer = p;
return result;
}
public T[] GetFirstX(long x)
{
long p = this.Pointer;
if (x > this.count)
x = this.count;
long gap = this.length - this.count;
this.Pointer = (this.Pointer + gap) % this.length;
T[] result = new T[x];
for (int i = 0; i < x; i++)
{
result[i] = Grab();
Next();
}
this.Pointer = p;
return result;
}
public void Clear()
{
this.data = new T[this.length];
this.count = 0;
}
private void Next()
{
this.Pointer++;
if (this.Pointer > this.length - 1)
this.Pointer = 0;
}
private void Previous()
{
this.Pointer--;
if (this.Pointer < 0)
this.Pointer = this.length - 1;
}
private T Grab()
{
return this.data[this.Pointer];
}
public AssemblyLine(long Length)
{
this.length = Length;
this.data = new T[Length];
}
}
Now I am curious if its possible to get that connected to Linq, providing something like this:
AssemblyLine<int> myAssemblyLine = new AssemblyLine(100);
// Insert some Stuff
List<int> myList = myAssemblyLine.Where(i => i > 5).ToList();
Any idea someone?
Almost all LINQ extension methods are declared on IEnumerable<T>, so as soon as your class implements that interface, you'll get it for free.
There are just couple methods that use non-generic IEnumerable, like Cast or OfType, but if you can get your class implement generic IEnumerable<T> it will be much better, because users won't have to call Cast<T> first, to get IEnumerable<T> and access all the other methods (as is right now the case for some legacy collections).
You have to implement IEnumerable<T> for .Where(). See Adding LINQ to my classes.
Once you implement IEnumerable<T> and all required methods, you will have access to these methods: http://msdn.microsoft.com/en-us/library/vstudio/system.linq.enumerable_methods(v=vs.100).aspx
Related
Lets say I have a list of items:
[a,b,b,a,c,d,a,d,b,c]
and I need to know, for each item, how many items along do I have to traverse till I get n unique items, (and return eg -1, or otherwise indicate if that's not possible)
So here, if n = 4, I would return
[6,5,4,6,5,5,4,-1,-1,-1]
since
a,b,b,a,c,d contains 4 unique elements
b,b,a,c,d contains 4 unique elements
b,a,c,d contains 4 unique elements,
a,c,d,a,d,b contains 4 unique elements
etc.
I used
List.Select((x,i) => {
var range = List.Skip(i).GroupBy(y => y).Take(n);
if (range.Count() == n)
return range.SelectMany(y => y).Count();
return -1;
});
Although i'm pretty sure this is horribly non-performant.
To try to minimize overhead, I created a ListSpan extension class for managing subparts of a List - something like ArraySegment for List, but (loosely) modeled on Span:
public class ListSpan<T> : IEnumerable<T>, IEnumerable {
List<T> baseList;
int start;
int len;
public ListSpan(List<T> src, int start = 0, int? len = null) {
baseList = src;
this.start = start;
this.len = len ?? (baseList.Count - start);
if (this.start + this.len > baseList.Count)
throw new ArgumentException("start+len > Count for ListSpan");
}
public T this[int n]
{
get
{
return baseList[start + n];
}
set
{
baseList[start + n] = value;
}
}
public class ListSpanEnumerator<Te> : IEnumerator<Te>, IEnumerator {
int pos;
List<Te> baseList;
int end;
Te cur = default(Te);
public ListSpanEnumerator(ListSpan<Te> src) {
pos = src.start - 1;
baseList = src.baseList;
end = src.start + src.len;
}
public Te Current => cur;
object IEnumerator.Current => Current;
public bool MoveNext() {
if (++pos < end) {
cur = baseList[pos];
return true;
}
else {
cur = default(Te);
return false;
}
}
public void Reset() => pos = 0;
public void Dispose() { }
}
public IEnumerator<T> GetEnumerator() => new ListSpanEnumerator<T>(this);
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
public static class ListExt {
public static ListSpan<T> Slice<T>(this List<T> src, int start = 0, int? len = null) => new ListSpan<T>(src, start, len);
}
Then I created an extension method to return the distance (in Take terms) required to get n unique items from an IEnumerable:
public static class IEnumerableExt {
public static int DistanceToUnique<T>(this IEnumerable<T> src, int n, IEqualityComparer<T> cmp = null) {
var hs = new HashSet<T>(cmp ?? EqualityComparer<T>.Default);
var pos = 0;
using (var e = src.GetEnumerator()) {
while (e.MoveNext()) {
++pos;
hs.Add(e.Current);
if (hs.Count == n)
return pos;
}
}
return -1;
}
}
Now the answer is relatively straight forward:
var ans = Enumerable.Range(0, src.Count).Select(p => src.Slice(p).DistanceToUnique(n));
Basically I go through each position in the original (src) List and compute the distance to n unique values from that position using a ListSpan of the List starting at that position.
This still isn't terribly efficient in that I am creating a HashSet for every element in the original List and putting all the following elements in it, and traversing the elements up to k! times for a k element List. Still trying to come up with something really efficient.
I have created a CustomList class with some methods such as Add(), Set(), and RemoveAt(). This CustomList class is meant to mimic the behavior of the List<> class without actually using it.
When debugging my program I noticed that when I input the index of the string I want removed, my code successfully removes that string. But when I call the print method, it double prints the last string in the array. I'm assuming the error is within RemoveAt() and not Print() because Print() works perfectly fine when RemoveAt() is not called. I was wondering if anybody could point me in the right direction.
class CustomList
{
private int count;
private String[] data;
public int Count
{
get { return count; }
set { value = count; }
}
public CustomList(int arrayNum)
{
data = new String[arrayNum];
}
public CustomList(): this(4)
{
}
public void Add (String item)
{
if (count > data.Length)
{
String[] temp = new String[count * 2];
for (int i = 0; i < data.Length; i++)
{
temp[i] = data[i];
}
data = temp;
}
data[count] = item;
count++;
}
public int IndexOf (String item)
{
for (int i = 0; i < data.Length; i++)
{
if (data[i].Contains(item))
{
return i;
}
}
return -1;
}
public bool Contains (String item)
{
if (IndexOf(item) == -1)
{
return false;
}
return true;
}
public void RemoveAt(int index)
{
if (index < count && index >= 0)
{
Array.Copy(data, index + 1, data, index, Count - (index + 1));
count--;
}
}
public bool Remove(String item)
{
if (data.Contains(item))
{
int index = Array.IndexOf(data, item);
RemoveAt(index);
return true;
}
return false;
}
public void Print()
{
for (int i = 0; i < count; i++)
{
Console.WriteLine(data[i]);
}
}
I'm a little confused with what you're saying, #germi. When I set the size to 4 and enter 4 strings, it successfully prints the 4 items in the array:
Your print loop should go from 0 to count-1, not from 0 to count. If you have 3 items (count == 3) then the indexes of those items are 0, 1, 2.
You're only getting away with accessing one too many items because of the way you're implementing Remove, which doesn't shrink the array (and so there still is a now-unused element at that index).
Change the <= into a <.
Also, the RemoveAt method should do count--, not Count--.
I've found myself in a position where I have to roll my own dynamic array implementation, due to various large performance benefits (in my case). However, after creating an enumerator for my version, and comparing the efficiency with the one List uses, I'm a bit bewildered; the List one is aproximately 30-40% faster than my version, even though it's much more complex.
Here's the important part of the List enumerator implementation:
public struct Enumerator : IEnumerator<T>, IDisposable, IEnumerator
{
private List<T> list;
private int index;
private int version;
private T current;
internal Enumerator(List<T> list)
{
this.list = list;
this.index = 0;
this.version = list._version;
this.current = default(T);
return;
}
public bool MoveNext()
{
List<T> list;
list = this.list;
if (this.version != list._version)
{
goto Label_004A;
}
if (this.index >= list._size)
{
goto Label_004A;
}
this.current = list._items[this.index];
this.index += 1;
return 1;
Label_004A:
return this.MoveNextRare();
}
public T Current
{
get { return this.current; }
}
}
And here's my very barebone version:
internal struct DynamicArrayEnumerator<T> : IEnumerator<T> where T : class
{
private readonly T[] internalArray;
private readonly int lastIndex;
private int currentIndex;
internal DynamicArrayEnumerator(DynamicArray<T> dynamicArray)
{
internalArray = dynamicArray.internalArray;
lastIndex = internalArray.Length - 1;
currentIndex = -1;
}
public T Current
{
get { return internalArray[currentIndex]; }
}
public bool MoveNext()
{
return (++currentIndex <= lastIndex);
}
}
I know this is micro-optimization, but I'm actually interested in understanding why the List enumerator is so much faster than mine. Any ideas? Thanks!
Edit:
As requested; the DynamicArray class (the relevant parts):
The enumerator is an inner class in this.
public struct DynamicArray<T> : IEnumerable<T> where T : class
{
private T[] internalArray;
private int itemCount;
internal T[] Data
{
get { return internalArray; }
}
public int Count
{
get { return itemCount; }
}
public DynamicArray(int count)
{
this.internalArray = new T[count];
this.itemCount = 0;
}
public IEnumerator<T> GetEnumerator()
{
return new DynamicArrayEnumerator<T>(this);
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
As for how I'm testing:
List<BaseClass> list = new List<BaseClass>(1000000);
DynamicArray<BaseClass> dynamicArray = new DynamicArray<BaseClass>(1000000);
// Code for filling with data omitted.
int numberOfRuns = 0;
float p1Total = 0;
float p2Total = 0;
while (numberOfRuns < 100)
{
PerformanceAnalyzer p1 = new PerformanceAnalyzer(() =>
{
int u = 0;
foreach (BaseClass b in list)
{
if (b.B > 100) // Some trivial task
u++;
}
});
p1.ExecuteAndClock();
p1Total += p1.TotalElapsedTicks;
PerformanceAnalyzer p2 = new PerformanceAnalyzer(() =>
{
int u = 0;
foreach (BaseClass b in dynamicArray)
{
if (b.B > 100) // Some trivial task
u++;
}
});
p2.ExecuteAndClock();
p2Total += p2.TotalElapsedTicks;
numberOfRuns++;
}
Console.WriteLine("List enumeration: " + p1Total / totalRuns + "\n");
Console.WriteLine("Dynamic array enumeration: " + p2Total / totalRuns + "\n");
The PerformanceAnalyzer class basically starts a Stopwatch, execute the supplied Action delegate, and then stop the Stopwatch afterwards.
Edit 2 (Quick answer to Ryan Gates):
There's a few reasons why I would want to roll my own, most importantly I need a very fast RemoveAt(int index) method.
Since I don't have to worry about the order of the list elements in my particular case, I can avoid the .Net built-in list's way of doing it:
public void RemoveAt(int index)
{
T local;
if (index < this._size)
{
goto Label_000E;
}
ThrowHelper.ThrowArgumentOutOfRangeException();
Label_000E:
this._size -= 1;
if (index >= this._size)
{
goto Label_0042;
}
Array.Copy(this._items, index + 1, this._items, index, this._size - index);
Label_0042:
this._items[this._size] = default(T);
this._version += 1;
return;
}
And instead using something along the lines of:
public void RemoveAt(int index)
{
// overwrites the element at the specified index with the last element in the array and decreases the item count.
internalArray[index] = internalArray[itemCount];
itemCount--;
}
Potencially saving enormous amounts of time in my case, if say the first 1000 elements in a long list have to be removed by index.
Okay, aside from benchmarking problems, here's how you can make your DynamicArray class more like List<T>:
public DynamicArrayEnumerator<T> GetEnumerator()
{
return new DynamicArrayEnumerator<T>(this);
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
Now, code which knows it's working with a dynamic array can iterate with a DynamicArrayEnumerator<T> without any boxing, and without virtual dispatch. This is exactly what List<T> does. The compiler notices when a type implements the pattern in a custom manner, and will use the types involved instead of the interfaces.
With your current code, you're getting no benefit from creating a struct - because you're boxing it in GetEnumerator().
Try the above change and fix the benchmark to work for longer. I'd expect to see a big difference.
I have a generic class defined like this
class MyGenericClass<T> where T : ICompareable
{
T[] data;
public AddData(T[] values)
{
data = values;
}
}
In mainForm, I create 3 random numbers, and add them as values, lets say 1, 2 and 3. So my T[] data; will look like this: [0]1 [1]2 [2]3
What I want to do is to remove 1 of these values from the array, how do I do that when I'm using generics. Lets say I want to remove 3 from the array so it would look like this[0]1 [1]2
Why don't you use a generic List (List<T>) instead of the array as a private member of your class to hold the data ?
As it is a private member, the 'outside world' cannot access the list, and you will have a much easier life since a List allows you to Add and Remove items easily.
class MyGenericClass<T> where T : ICompareable
{
private List<T> data = new List<T>();
public AddData(params T[] values)
{
data.AddRange (values);
}
public RemoveData( T value )
{
data.Remove (value);
}
public RemoveData( params T[] values )
{
for( int i = 0; i < values.Length; i++ )
{
data.Remove (values[i]);
}
}
}
Once you've done this, you can use the Add member-method of the List to add items, and the Remove member method to remove items. Simple as that.
I've used the params keyword in the AddData method so that you can do this:
var x = new MyGenericClass<int>();
x.AddData(1);
x.AddData(2, 3, 4);
x.AddData(somIntegerList.ToArray());
Change your class to look like this (I also implemented Frederik's suggestion of using a List instead of a array.
class MyGenericClass<T> where T : ICompareable
{
List<T> data;
public AddData(T value)
{
data.Add(value);
}
public RemoveData(T value)
{
data.Remove(value);
}
}
If for some reasaon, you insist on using an array, the remove method may look something like this
public RemoveData(T value)
{
data = data.Where( e => e.CompareTo(value) != 0).ToArray();
}
I kind of had the same question, because I was writing a dynamically sized array to practice creating generic classes.
I found that you can either: move all of the elements down and then set the last element equal to default(T), or create a new array of size-1 to be filled with the remaining elements.
Ex:
public class Array<T>
{
private T[] _array { get; set; }
private int _max { get; set; }
private int _size { get; set; }
public Array()
{
_max = 10;
_array = new T[_max];
_size = 0;
}
public T Remove(int i)
{
if (i >= _size || i < 0) return default(T);
var tmp = _array[i];
for (var j = i; j < _size-1; ++j)
{
_array[j] = _array[j + 1];
}
_array[_size - 1] = default(T);
_size--;
return tmp;
}
}
Or...
public T Remove(int i) {
var tmp = new T[_size-1];
for(var j=0; j < i; ++j)
{
tmp[j] = _array[j];
}
var result = _array[i];
for(var j=i+1; j < _size-1; ++j)
{
tmp[j] = _array[j];
}
_array = null;
_array = tmp;
return result;
}
Basically, I have a collection of objects each implement a member of Type IValueCollection.
public interface IValueCollection : IEnumerable<decimal>
{
decimal this[int index] { get; set; }
}
MeasurementCollection.Values is of type IValueCollection.
With the logic below I want to pivot a collection of IValueCollection and wrote the extension method below.
public static IEnumerable<IValueCollection> PivotValues(this MeasurementCollection items)
{
if(items.IsQuantized())
{
int s = (int)items.First().Template.Frequency;
int c = items.Count;
for (int n = 0; n < s; n++)
{
IValueCollection v = new MeasurementValueCollection(c);
for (int m = 0; m < c; m++)
v[m] = items.ElementAt(m).Values[n];
yield return v;
}
}
}
should do
{{1,2,3}{4,5,6}{7,8,9}} results in {{1,4,7},{2,5,8},{3,6,9}}
However I think there is some nicer, slimmer and more readable expression to do this
can somebody point me in the right direction?
edit
info about underlying classes
interface IValueCollection : IEnumerable<decimal>
class MeasurementCollection : ICollection<IMeasurement>
interface IMeasurement
{
IMeasurementTemplate Template { get; }
......
}
interface IMeasurementTemplate
{
.....
MeasurementFrequency Frequency { get; }
}
I would, personally, force the evaluation of your collection in advance, and use it as an array. Right now, each time you call ElementAt, you're going to evaluate the IEnumerable<T> again, causing a lot of repeated searching.
By forcing it to evaluate to an array in advance, you simplify the entire process. Something like:
public static IEnumerable<IValueCollection> PivotValues(this MeasurementCollection items)
{
if(items.IsQuantized())
{
int elementLength = (int)items.First().Template.Frequency;
var itemArray = items.ToArray();
for (int n = 0; n < itemArray.Length; n++)
{
IValueCollection v = new MeasurementValueCollection(elementLength);
for (int m = 0; m < elementLength; m++)
{
v[m] = itemArray[m].Values[n];
}
yield return v;
}
}
else
yield break; // Handle the case where IsQuantized() returns false...
}
If you control MeasurementValueCollection, I would add a constructor which takes an IEnumerable<decimal> as input, as well. You could then do:
public static IEnumerable<IValueCollection> PivotValues(this MeasurementCollection items)
{
if(items.IsQuantized())
{
var elements = Enumerable.Range(0, (int)items.First().Template.Frequency);
var itemArray = items.ToArray();
foreach(var element in elements)
yield return new MeasurementValueCollection(
itemArray.Select(
(item,index) => itemArray[index].Value[element]
)
);
}
else
yield break; // Handle the case where IsQuantized() returns false...
}