Skip to content

Instantly share code, notes, and snippets.

@jabez007
Last active January 17, 2019 20:04
Show Gist options
  • Save jabez007/43c41e1cc7f2d1649c07486230f76162 to your computer and use it in GitHub Desktop.
Save jabez007/43c41e1cc7f2d1649c07486230f76162 to your computer and use it in GitHub Desktop.
A C# implementation for a Python-like List object
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();
}
}
}
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