Non-0 based arrays in C# with traditional [ ] array syntax? - c#

I'd like to be able to create an array in C# with an arbitrary range of index bounds, e.g., a 16 element array with indices of 100-115.
Native arrays in C# are 0-based, but I'm told (e.g., in Luaan's comment here), that the C# Array class allows arbitrary lower and upper bounds. But in the examples I've seen elements in the Array class are accessed via myArray.GetValue() and myArray.SetValue() instead of conventional array syntax like myArray [ foo ].
Array arr = Array.CreateInstance(typeof(string), new[]{16}, new[]{100});
Console.WriteLine(arr.Length); // 16
arr.SetValue("foo", 100);
Console.WriteLine(arr.GetValue(100)); // foo
Is there any way to make an array with some arbitrary starting index, like [100] that I can access with traditional [ ] syntax in C#?

You could create a class that implements the decorator pattern: just implement the IList interface (wich is also implemented by Array) and do whatever shifting you want on the this [int index] property.
The decorator pattern is described here:
http://www.codeproject.com/Articles/479635/UnderstandingplusandplusImplementingplusDecoratorp

The Array class does not support this, but you can write your own array class with one-based indices:
public class OneBasedArray<T>
{
public T[] InnerArray;
public T this[int i]
{
get { return InnerArray[i-1]; }
set { InnerArray[i-1] = value; }
}
}
And then use it like this:
var myArray = new OneBasedArray<int> { InnerArray = new int[]{ 1, 2, 3, 4, 5 } };
for(int i = 1; i <=5; i++)
{
Console.WriteLine(myArray[i]);
}
This code is only to get the idea, such a class would of course need a nicer interface.

You can only use an array's indexer when it's a 0-indexed array.
You can use an indexer for a custom, non-array, type, and use whatever logic you want for it, such as making it non-zero-indexed, but that's not an option for arrays.

I think Lukas' answer is probably the easiest way to handle this, but if, for some reason, you really wanted to use Array.CreateInstance (not sure why you would - maybe some external library might insist on it?), you could wrap it in a class like this:
public class NonZeroArray<T>
{
private readonly Array array;
public T this[int i]
{
get { return (T)array.GetValue(i); }
set { array.SetValue(value, i); }
}
public NonZeroArray(int length, int lowerBounds = 0)
{
array = Array.CreateInstance(typeof(T), new int[] { length}, new int[] { lowerBounds } );
}
}
You could obviously make this a lot prettier (and easier to work with) by having it implement the rest of IList<T>. And if you really need the native array, you could implement a property with a getter to expose it when needed.
Using it would be simply:
var myNonZeroArray = new NonZeroArray<string>(16,100);
myNonZeroArray[100] = "foo";
Console.WriteLine(myNonZeroArray[100]); // prints "foo"

Here's a custom class that extends IList<T> to provide functionality for starting at a non-zero index:
public class NonZeroList<T> : IList<T>
{
private int startIndex;
private List<T> inner;
public NonZeroList(int startIndex, IEnumerable<T> content)
{
this.startIndex = startIndex;
inner = content.ToList();
}
public NonZeroList(int startIndex)
{
this.startIndex = startIndex;
inner = new List<T>();
}
public T this[int i]
{
get
{
return inner[i - startIndex];
}
set
{
inner[i - startIndex] = value;
}
}
public IEnumerator<T> GetEnumerator()
{
foreach (T i in inner)
yield return i;
yield break;
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return inner.GetEnumerator();
}
public int IndexOf(T item)
{
return inner.IndexOf(item) + startIndex;
}
public void Insert(int index, T item)
{
inner.Insert(index - startIndex, item);
}
public void RemoveAt(int index)
{
inner.RemoveAt(index - startIndex);
}
public void Add(T item)
{
inner.Add(item);
}
public void Clear()
{
inner.Clear();
}
public bool Contains(T item)
{
return inner.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
inner.CopyTo(array, arrayIndex);
}
public int Count
{
get { return inner.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public bool Remove(T item)
{
return inner.Remove(item);
}
}
To use it, you initialize it just as you would a normal List<T>, but with the start index specified (e.g. NonZeroList<int> myList = new NonZeroList<int>(20) { 0, 1, 2, 3 };). You can then use it just as you would a normal List<T> or T[].
If you want to use it as an array instead of a list, then you can simply add bounds checking or implement IEnumerable<T> instead of IList<T>, and create utility functions yourself.

Related

Is There a C# Generic Container That Is List<T> but also HashSet<T>

I'm looking for a C# generic container that it's a List<T>, but no repeated elements allowed.
In another word, it's a Set<T>, but can also be accessed via [index] operator.
Thanks.
As suggested in the comments, you could implement IList<T> that delegates to an inner List<T> instance, and guards add and remove calls with using a HashSet<T>:
public class UniqueList<T> : IList<T>
{
private readonly List<T> list=new List<T>();
private readonly HashSet<T> set=new HashSet<T>();
public IEnumerator<T> GetEnumerator()
{
return list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add(T item)
{
if(set.Add(item))
{
list.Add(item);
}
}
public void Clear()
{
set.Clear();
list.Clear();
}
public bool Contains(T item)
{
return set.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
list.CopyTo(array,arrayIndex);
}
public bool Remove(T item)
{
if(set.Remove(item))
{
list.Remove(item);
return true;
}
return false;
}
public int Count { get { return list.Count; } }
public bool IsReadOnly { get { return false; } }
public int IndexOf(T item)
{
return list.IndexOf(item);
}
public void Insert(int index, T item)
{
if(set.Add(item))
{
list.Insert(index, item);
}
}
public void RemoveAt(int index)
{
T item = list[index];
set.Remove(item);
list.RemoveAt(index);
}
public T this[int index]
{
get { return list[index]; }
set {
T item = list[index];
set.Remove(item);
if(set.Add(value))
{
list[index] = value;
}
else
{
set.Add(item);
throw new Exception();
}
}
}
}
I didn't compile this code, but you get the idea...
No such thing is provided in the framework (and HashSet<T> does not guarantee any specific order, so you can't cheat with ElementAt). The closest inbuilt you could use would be something like SortedList<T,anything> (the "anything" there doesn't matter, and could be T, int, whatever), for example:
var data = new SortedList<string, int>();
data["abc"] = 1;
data["def"] = 1;
data["abc"] = 1;
var thisIsTrue = data.ContainsKey("def");
var thisIsFalse = data.ContainsKey("ghi");
for (int i = 0; i < data.Count; i++) // 2 iterations
Console.WriteLine(data.Keys[i]); // abc, def
However; it is important to note that the guaranteed order here is key order, not insertion order. The index of keys is available via data.IndexOfKey.
You could use the OrderedDictionary. If you use your type for both key and value type, and use the same object as both key and value, you get the behavior you need (You could also use the keys collection for index based retrieval; and stick dummy data into the value, but I'm not sure what you would gain).

C# IEnumerable, IEnumerator Reset Function Not Get Called

I'm basicly trying to make my class able to iterate using foreach. I read this tutorial. MSDN. It seems very straight forward. However, I have a problem when I want to iterate second time. I debugged it; and it turned out that it doesn't call the Reset() function.
Class A
class A : IEnumerable, IEnumerator
{
int[] data = { 0, 1, 2, 3, 4 };
int position = -1;
public object Current
{
get
{
return data[position];
}
}
public bool MoveNext()
{
position++;
return (position < data.Length);
}
public void Reset()
{
position = -1;
}
public IEnumerator GetEnumerator()
{
return (IEnumerator)this;
}
}
When I run the following main function; it never calls Reset() function. So, after one loop I never be able to iterate my class again.
Main
static void Main(string[] args)
{
A a = new A();
foreach (var item in a)
{
Console.WriteLine(item);
}
Console.WriteLine("--- First foreach finished. ---");
foreach (var item in a)
{
Console.WriteLine(item);
}
}
Output:
0
1
2
3
4
--- First foreach finished. ---
Press any key to continue . . .
Any thoughts?
Each time foreach is called, it asks for a new IEnumerator. Returning your class instance is a bad idea - you should make a separate class to implement the IEnumerator, and return it instead.
This is often done by using a nested (private) class, and returning an instance of it. You can pass the class A instance to the private class (giving it access to data), and put the position field in that class. It would allow more than one enumerator to be created simulatenously, and will work properly with subsequent foreach calls.
For example, to modify your code, you'd do something like:
using System;
using System.Collections;
class A : IEnumerable
{
int[] data = { 0, 1, 2, 3, 4 };
public IEnumerator GetEnumerator()
{
return new AEnumerator(this);
}
private class AEnumerator : IEnumerator
{
public AEnumerator(A inst)
{
this.instance = inst;
}
private A instance;
private int position = -1;
public object Current
{
get
{
return instance.data[position];
}
}
public bool MoveNext()
{
position++;
return (position < instance.data.Length);
}
public void Reset()
{
position = -1;
}
}
}
Note that you can also just return the array's enumerator directly (though I was assuming you were trying to learn how to make clean enumerators):
class A : IEnumerable
{
int[] data = { 0, 1, 2, 3, 4 };
public IEnumerator GetEnumerator()
{
return data.GetEnumerator();
}
}
Finally, you can use iterators to implement this in a far simpler manner:
class A : IEnumerable
{
int[] data = { 0, 1, 2, 3, 4 };
public IEnumerator GetEnumerator()
{
for (int i=0;i<data.Length;++i)
yield return data[i];
}
}
That being said, I would strongly recommend implementing IEnumerable<int> in addition to IEnumerable. Generics make this far nicer in terms of usage.
Reset() was basically a mistake. There's already a known method to get a clean enumerator if possible: GetEnumerator().
It is a requirement in the specification that iterator block implementations (for the iterator) throw an exception for this method, hence in the general case it is formally known that it can't be expected to work, and simply: nobody ever calls it. Frankly, they should also have marked it [Obsolete] on the API !
Additionally, many sequences are non-repeatable. Think of iterators sat on a NetworkStream or a random numer generator. Because iterators (in the general case) are not required to be repeatable, you should aim, where possible, to iterate them at most once. Perhaps buffering via ToList() if that is not possible.
"foreach" does not involve Reset() at any point. Just GetEnumerator(), MoveNext(), Current and Dispose().
The enumeration doesn't call Reset. You need to create a new instance of an enumerator, which will likely mean creating a separate class for the enumerator (i.e., not using the same type for the IEnumerable and IEnumerator), like in the code below:
public class StackOverflow_11475328
{
class A : IEnumerable
{
int[] data = { 0, 1, 2, 3, 4 };
public IEnumerator GetEnumerator()
{
return new AEnumerator(this);
}
class AEnumerator : IEnumerator
{
private A parent;
private int position = -1;
public AEnumerator(A parent)
{
this.parent = parent;
}
public object Current
{
get { return parent.data[position]; }
}
public bool MoveNext()
{
position++;
return (position < parent.data.Length);
}
public void Reset()
{
position = -1;
}
}
}
public static void Test()
{
A a = new A();
foreach (var item in a)
{
Console.WriteLine(item);
}
Console.WriteLine("--- First foreach finished. ---");
foreach (var item in a)
{
Console.WriteLine(item);
}
}
}
Both Reed and Carlos are correct. Here is one way you can do this, since int[] implements IEnumerable and IEnumerable<int>
class A : IEnumerable
{
int[] data = { 0, 1, 2, 3, 4 };
public IEnumerator GetEnumerator()
{
return data.GetEnumerator();
}
}
Or, to be more strongly typed, you can use the generic form of IEnumerable:
class A : IEnumerable<int>
{
int[] data = { 0, 1, 2, 3, 4 };
public IEnumerator<int> GetEnumerator()
{
return ((IEnumerable<int>)data).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return data.GetEnumerator();
}
}

Class<type> in C#

I have a class and want to work with it as Lists: e.g. List<int>, List<string>, ... , List<T>
I have a class Randomizor which will take the collection data type that will be shuffled. How can I do so?
class Randomizor<T>
{
public Randomizor()
{
}
public Array Shuffle(Array toShuffle)
{
}
}
Create a generic class like so:
class Randomizer<TList, TType> where TList : IList<TType>
{
public TList Randomize(TList list)
{
// ...
}
}
Or like so:
class Randomizer<T>
{
public IList<T> Randomize(IList<T> list)
{
// ...
}
}
Not very clear question... do you mean something like this?
public static class Randomizer<T>
{
public static T GetRandom(List<T> list)
{
T value = default(T);
// Perform some random logic.
return value;
}
}
EDIT: I found two superior impementations after a little digging so I would suggest those in preference.
An extension method for this purpose and already been suggested previously here
I include the code paraphrased to Shuffle below.
public static IEnumerable<T> Shuffle<T> (this IEnumerable<T> source)
{
Random random = new Random ();
T [] copy = source.ToArray ();
for (int i = copy.Length - 1; i >= 0; i--)
{
int index = random.Next (i + 1);
yield return copy [index];
copy [index] = copy [i];
}
}
And an interesting solution adapted from this linq approach
public static IEnumerable<T> Shuffle<T> (this IEnumerable<T> source)
{
Random random = new Random ();
return source.OrderBy(i => Random.Next()).AsEnumerable();
}
The orignal answer but slower than the edits
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> sequence)
{
Random random = new Random();
List<T> copy = sequence.ToList();
while (copy.Count > 0)
{
int index = random.Next(copy.Count);
yield return copy[index];
copy.RemoveAt(index);
}
}
If you like one of these you should up vote the linked answer.
If you are very concerned about randomness, you could upgrade to one of the RNG algorithms from the Crypto API and seed it with some non deterministic value, like somthing generated from recent mouse activity. I suspect that would be overkill and it would degrade performance.
class Randomizor<T>
{
public Randomizor()
{
}
public List<T> Shuffle(List<T> toShuffle)
{
}
}
class Randomizer<T>
{
public Randomizer(ICollection<T> collection)
{
//Do something with collection using T as the type of the elements
}
}
However you may want to go for a generic extension method
static class Randomizer
{
public static void Randomize<T>(this ICollection<T> collection)
{
//randomize the collection
}
}
and the usage:
List<int> list = new List<int> { 1, 2, 3, 4, 5 };
list.Randomize();
Maybe like this:
public List<T> Shuffle<T>(List<T> toShuffle)
{
return toShuffle.OrderBy(x => Guid.NewGuid()).ToList();
}
Or as an extension method
public static class Extensions
{
public static List<T> Shuffle<T>(this List<T> toShuffle)
{
return toShuffle.OrderBy(x => Guid.NewGuid()).ToList();
}
}

How can I implement IEnumerable<T> on a collection that has a MultiDimensional Array inner list?

I have a collection:
interface IPinCollection : IEnumerable<IPin>
{
IPin this[int [,] indices] { get; set; }
}
Basically it has an innerlist as matrix which has IPin instance in its each [rowindex,columnIndex].
What I want to achieve is to be able to walkthrough the all IPin instances of this matrix with for..each.
Can you suggest me a thread-safe,simple and quick way to implement IEnumerable to achieve this?
If your underlying property is an Array, you can use Array.GetLength(int dimension) to get the length of the array in the specified dimension, although in that case you can simply use its built-in enumerator.
This works, for example:
int[,] arr = new int[,]
{
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 },
{ 10, 11, 12 }
};
foreach (int i in arr)
Console.WriteLine(i);
It means you can simply return values from the array, in the order its enumerator returns them:
class PinCollection : IPinCollection
{
private IPin[,] _array;
#region IEnumerable<int> Members
public IEnumerator<int> GetEnumerator()
{
foreach (IPin i in _array)
yield return i;
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator
System.Collections.IEnumerable.GetEnumerator()
{
foreach (IPin i in _array)
yield return i;
}
#endregion
}
If the array is of known dimension, for example private readonly IPin[,] data;, then actually pretty simply (since you can already foreach over a multi-dimensional array; but note that T[*,*] doesn't itself implement IEnumerable<T> - since that isn't technically a requirement for foreach):
public IEnumerator<IPin> GetEnumerator()
{
foreach (IPin pin in pins) yield return pin;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

Is there a SortedList<T> class in .NET? (not SortedList<K,V>)

I need to sort some objects according to their contents (in fact according to one of their properties, which is NOT the key and may be duplicated between different objects).
.NET provides two classes (SortedDictionary and SortedList), and both are implemented using a binary tree. The only differences between them are
SortedList uses less memory than SortedDictionary.
SortedDictionary has faster insertion and removal operations for unsorted data, O(log n) as opposed to O(n) for SortedList.
If the list is populated all at once from sorted data, SortedList is faster than SortedDictionary.
I could achieve what I want using a List, and then using its Sort() method with a custom implementation of IComparer, but it would not be time-efficient as I would sort the whole List each time I want to insert a new object, whereas a good SortedList would just insert the item at the right position.
What I need is a SortedList class with a RefreshPosition(int index) to move only the changed (or inserted) object rather than resorting the whole list each time an object inside changes.
Am I missing something obvious ?
Maybe I'm slow, but isn't this the easiest implementation ever?
class SortedList<T> : List<T>
{
public new void Add(T item)
{
Insert(~BinarySearch(item), item);
}
}
http://msdn.microsoft.com/en-us/library/w4e7fxsh.aspx
Unfortunately, Add wasn't overrideable so I had to new it which isn't so nice when you have List<T> list = new SortedList<T>; which I actually needed to do.... so I went ahead and rebuilt the whole thing...
class SortedList<T> : IList<T>
{
private List<T> list = new List<T>();
public int IndexOf(T item)
{
var index = list.BinarySearch(item);
return index < 0 ? -1 : index;
}
public void Insert(int index, T item)
{
throw new NotImplementedException("Cannot insert at index; must preserve order.");
}
public void RemoveAt(int index)
{
list.RemoveAt(index);
}
public T this[int index]
{
get
{
return list[index];
}
set
{
list.RemoveAt(index);
this.Add(value);
}
}
public void Add(T item)
{
list.Insert(~list.BinarySearch(item), item);
}
public void Clear()
{
list.Clear();
}
public bool Contains(T item)
{
return list.BinarySearch(item) >= 0;
}
public void CopyTo(T[] array, int arrayIndex)
{
list.CopyTo(array, arrayIndex);
}
public int Count
{
get { return list.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public bool Remove(T item)
{
var index = list.BinarySearch(item);
if (index < 0) return false;
list.RemoveAt(index);
return true;
}
public IEnumerator<T> GetEnumerator()
{
return list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return list.GetEnumerator();
}
}
Or perhaps something like this is a more appropriate Remove function...
public bool Remove(T item)
{
var index = list.BinarySearch(item);
if (index < 0) return false;
while (((IComparable)item).CompareTo((IComparable)list[index]) == 0)
{
if (item == list[index])
{
list.RemoveAt(index);
return true;
}
index++;
}
return false;
}
Assuming items can compare equal but not be equal...
I eventually decided to write it :
class RealSortedList<T> : List<T>
{
public IComparer<T> comparer;
public int SortItem(int index)
{
T item = this[index];
this.RemoveAt(index);
int goodposition=FindLocation(this[index], 0, this.Count);
this.Insert(goodposition, item);
return goodposition;
}
public int FindLocation(T item, int begin, int end)
{
if (begin==end)
return begin;
int middle = begin + end / 2;
int comparisonvalue = comparer.Compare(item, this[middle]);
if (comparisonvalue < 0)
return FindLocation(item,begin, middle);
else if (comparisonvalue > 0)
return FindLocation(item,middle, end);
else
return middle;
}
}
Don't forget that inserting an item into a list backed by an array can be an expensive operation - inserting a bunch of items and then sorting may well be quicker unless you really need to sort after every single operation.
Alternatively, you could always wrap a list and make your add operation find the right place and insert it there.
I've solved this problem in the past by writing an extension method that does a binary search on a IList, and another that does an insert. You can look up the correct implementation in the CLR source because there's a built-in version that works only on arrays, and then just tweak it to be an extension on IList.
One of those "should be in the BCL already" things.
What I need is a SortedList class with
a RefreshPosition(int index) to move
only the changed (or inserted) object
rather than resorting the whole list
each time an object inside changes.
Why would you update using an index when such updates invalidate the index? Really, I would think that updating by object reference would be more convenient. You can do this with the SortedList - just remember that your Key type is the same as the return type of the function that extracts the comparable data form the object.
class UpdateableSortedList<K,V> {
private SortedList<K,V> list = new SortedList<K,V>();
public delegate K ExtractKeyFunc(V v);
private ExtractKeyFunc func;
public UpdateableSortedList(ExtractKeyFunc f) { func = f; }
public void Add(V v) {
list[func(v)] = v;
}
public void Update(V v) {
int i = list.IndexOfValue(v);
if (i >= 0) {
list.RemoveAt(i);
}
list[func(v)] = v;
}
public IEnumerable<T> Values { get { return list.Values; } }
}
Something like that I guess.

Categories

Resources