Last active
January 17, 2019 20:04
-
-
Save jabez007/43c41e1cc7f2d1649c07486230f76162 to your computer and use it in GitHub Desktop.
A C# implementation for a Python-like List object
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
namespace SliceableList | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
var myList = new PyList<int>() | |
{ | |
1, 2, 3, 4, 5, 6, 7, 8, 9, 10 | |
}; | |
Console.WriteLine(myList[-1]); // 10 | |
Console.WriteLine(myList[null, null, -1]); // [10, 9, 8, 7, 6, 5, 4, 5, 2, 1] | |
Console.WriteLine(myList[null, null, 2]); // [1, 3, 5, 7, 9] | |
Console.WriteLine(myList[null, null, -2]); // [10, 8, 6, 4, 2] | |
Console.WriteLine(myList[null, null, -3]); // [10, 7, 4, 1] | |
Console.WriteLine(myList[3, 5]); // [4, 5] | |
Console.WriteLine(myList[3, 5, -1]); // [] | |
Console.WriteLine(myList[5, 3, -1]); // [6, 5] | |
Console.ReadLine(); | |
myList[null, null, 2] = new PyList<int>() { 0, 0, 0, 0, 0 }; | |
Console.WriteLine(myList); // [0, 2, 0, 4, 0, 6, 0, 8, 0, 10] | |
myList = new PyList<int>() | |
{ | |
1, 2, 3, 4, 5, 6, 7, 8, 9, 10 | |
}; | |
myList[null, null, -2] = new PyList<int>() { 0, 0, 0, 0, 0 }; | |
Console.WriteLine(myList); // [1, 0, 3, 0, 5, 0, 7, 0, 9, 0] | |
Console.ReadLine(); | |
myList = new PyList<int>() | |
{ | |
1, 2, 3, 4, 5, 6, 7, 8, 9, 10 | |
}; | |
Console.WriteLine(myList); | |
try | |
{ | |
myList[null, null, 3] = new PyList<int>() { 0, 0, 0, 0, 0 }; | |
} | |
catch (ArgumentException ex) | |
{ | |
Console.WriteLine(ex.Message); | |
Console.WriteLine(myList); | |
} | |
try | |
{ | |
myList[null, null, 3] = new PyList<int>() { 0 }; // exception | |
} | |
catch (ArgumentException ex) | |
{ | |
Console.WriteLine(ex.Message); | |
Console.WriteLine(myList); | |
} | |
Console.ReadLine(); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
namespace SliceableList | |
{ | |
public class PyList<T> : IList<T> | |
{ | |
protected List<T> list; | |
public PyList() | |
{ | |
list = new List<T>(); | |
} | |
public PyList(int capacity) | |
{ | |
list = new List<T>(capacity); | |
} | |
public PyList(IEnumerable<T> collection) | |
{ | |
list = new List<T>(collection); | |
} | |
protected int FixedIndex(int index) | |
{ | |
if (index < 0) | |
{ | |
return index + Count; | |
} | |
return index; | |
} | |
public T this[int index] | |
{ | |
get => ((IList<T>)list)[FixedIndex(index)]; | |
set => ((IList<T>)list)[FixedIndex(index)] = value; | |
} | |
public PyList<T> this[int? startingIndex, int? exclusiveEndIndex, int step = 1] | |
{ | |
get | |
{ | |
if (step == 0) | |
{ | |
throw new ArgumentException("slice step cannot be zero"); | |
} | |
return GetSlice( | |
FixedIndex(startingIndex ?? (step < 0 ? Count - 1 : 0)), | |
GetExclusiveEndIndex(exclusiveEndIndex, step), | |
step, | |
new PyList<T>()); | |
} | |
set | |
{ | |
if (step == 0) | |
{ | |
throw new ArgumentException("slice step cannot be zero"); | |
} | |
list = SetSlice( | |
FixedIndex(startingIndex ?? (step < 0 ? Count - 1 : 0)), | |
GetExclusiveEndIndex(exclusiveEndIndex, step), | |
step, | |
new List<T>(list), // don't update the list if an exception is thrown | |
value); | |
} | |
} | |
protected int GetExclusiveEndIndex(int? exclusiveEndIndex, int step) | |
{ | |
int _exclusiveEndIndex = exclusiveEndIndex ?? (step < 0 ? -1 : Count); | |
if (exclusiveEndIndex.HasValue && _exclusiveEndIndex < 0) // the negative was specifically passed in | |
{ | |
_exclusiveEndIndex += Count; | |
} | |
return _exclusiveEndIndex; | |
} | |
protected PyList<T> GetSlice(int startingIndex, int exclusiveEndIndex, int step, PyList<T> slice) | |
{ | |
// if step is negative we want the starting index to be greater than the end index | |
// if step is positive we want the starting index to be less than the end index | |
if ((step < 0 && startingIndex <= exclusiveEndIndex) || | |
(step > 0 && startingIndex >= exclusiveEndIndex)) | |
{ | |
return slice; | |
} | |
slice.Add(this[startingIndex]); | |
return GetSlice(startingIndex += step, exclusiveEndIndex, step, slice); | |
} | |
protected List<T> SetSlice(int startingIndex, int exclusiveEndIndex, int step, List<T> list, PyList<T> slice) | |
{ | |
// if step is negative we want the starting index to be greater than the end index | |
// if step is positive we want the starting index to be less than the end index | |
if ((step < 0 && startingIndex <= exclusiveEndIndex) || | |
(step > 0 && startingIndex >= exclusiveEndIndex)) | |
{ | |
if (slice.Count > 0) | |
{ | |
throw new ArgumentException("Given squence size does not match the requested slice size"); | |
} | |
return list; | |
} | |
if (slice.Count <= 0) | |
{ | |
throw new ArgumentException("Given squence size does not match the requested slice size"); | |
} | |
list[startingIndex] = slice[0]; | |
return SetSlice(startingIndex += step, exclusiveEndIndex, step, list, slice[1, null]); | |
} | |
public int Count => ((IList<T>)list).Count; | |
public bool IsReadOnly => ((IList<T>)list).IsReadOnly; | |
public void Add(T item) | |
{ | |
((IList<T>)list).Add(item); | |
} | |
public void Clear() | |
{ | |
((IList<T>)list).Clear(); | |
} | |
public bool Contains(T item) | |
{ | |
return ((IList<T>)list).Contains(item); | |
} | |
public void CopyTo(T[] array, int arrayIndex) | |
{ | |
((IList<T>)list).CopyTo(array, arrayIndex); | |
} | |
public IEnumerator<T> GetEnumerator() | |
{ | |
return ((IList<T>)list).GetEnumerator(); | |
} | |
public int IndexOf(T item) | |
{ | |
return ((IList<T>)list).IndexOf(item); | |
} | |
public void Insert(int index, T item) | |
{ | |
((IList<T>)list).Insert(FixedIndex(index), item); | |
} | |
public bool Remove(T item) | |
{ | |
return ((IList<T>)list).Remove(item); | |
} | |
public void RemoveAt(int index) | |
{ | |
((IList<T>)list).RemoveAt(FixedIndex(index)); | |
} | |
IEnumerator IEnumerable.GetEnumerator() | |
{ | |
return ((IList<T>)list).GetEnumerator(); | |
} | |
public override string ToString() | |
{ | |
return string.Format("[{0}]", string.Join(", ", list)); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment