2

I am trying to create:

  • Sparse Array with arbitrary indexing and
  • have have Sparse Array inherit IEnumerable.

So far I have the indexing... the IEnumerable part I don't know what to do.

class SparseArray : IEnumerable
{
    private Dictionary<object[], object> Items = new Dictionary<object[], object>();
    private int Counter = -1;
    public object this[params object[] Key]
    {
        set { Items.Add(Key, value); }
        get { object B; bool Tau = Items.TryGetValue(Key, out B); return B; }
    }
    public IEnumerator GetEnumerable()
    {
        ///
    }
}
class Program
{
    static void Main(string[] args)
    {
        uint W = 5;
        Potato P = new Potato(W, "Spudz");
        Potato Q = new Potato(W+2, "Super Spudz");
        SparseArray Pile = new SparseArray();
        Pile[1,2,3,4,5,Q] = "String";
        Pile["String",P] = "Strung";
        Pile[1.2030,"pi"] = true;
        foreach ( object Val in Pile)
        {
            Console.WriteLine(Val);
        }
        Console.ReadKey();
    }
}
struct Potato
{
    private string _Name;
    private uint _Weight;
    public string Name
    {   set { _Name = value; }
        get { return _Name; }
    }
    public uint Weight
    {
        set { _Weight = value; }
        get { return _Weight; }
    }
    public Potato(uint weight, string name)
    {
        _Weight = weight;
        _Name = name;
    }
}

How can I get the Sparse Array object to loop through its dictionary within the foreach loop?

EDIT UPDATE

I have made slight revision to the code thanks to the input from everybody:

public class ObjectArrayComparer : IEqualityComparer<object[]>
{
    // Determines whether x and y are equal or not
    public bool Equals(object[] x, object[] y)
    {
        return object.ReferenceEquals(x, y) // Returns true if they are the same array instance
            || (x != null && y != null && x.SequenceEqual(y));  // Returns true if x and y are not null and have the same elements (order dependent)
    }

    // Function that allow to fastly determine if an element is in a set of not.        
    // This function must have the following property:
    //   x.Equals(y) implies GetHashCode(x) == GetHashCode(y)
    public int GetHashCode(object[] obj)
    {
        if (obj == null)
            return 0;

        // Unchecked sum of the Hash Codes of all elements in obj
        return unchecked(obj.Select(o => o != null ? o.GetHashCode() : 0).Aggregate(0, (a, b) => a + b));
    }
}
class SparseArray : IEnumerable
{
    private Dictionary<object[], object> Items = new Dictionary<object[], object>(new ObjectArrayComparer());
    private int Counter = -1;
    public object this[params object[] Key]
    {
        set { Items.Add(Key, value); }
        get { 
                object B;
                if (Items.TryGetValue(Key, out B) == true)
                {
                    return Items[Key];
                }
                else
                {
                    //In computer science, a sparse array is an array in which most of the elements have the same value (known as the default value—usually 0 or null).
                    //So If the key does not exist, return null.   
                    return null;
                }

            }
        //get { object B; bool Tau = Items.TryGetValue(Key, out B); return B; }
    }
    public IEnumerator GetEnumerator()
    {
        return Items.Values.GetEnumerator();
    }
}
class Program
{
    static void Main(string[] args)
    {
        uint W = 5;
        Potato P = new Potato(W, "Spudz");
        Potato Q = new Potato(W+2, "Super Spudz");
        SparseArray Pile = new SparseArray();
        Pile[1,2,3,4,5,Q] = "String";
        Pile["String",P] = "Strung";
        Pile[1.2030,"pi"] = true;
        foreach ( object Val in Pile)
        {
            Console.WriteLine(Val);
        }
        Console.WriteLine(Pile[1.2030, "pi"]);
        Console.WriteLine(Pile["String", P]);
        Console.WriteLine(Pile["String", P]);
        Console.WriteLine(Pile["String", Q]);
        Console.ReadKey();
    }
}
struct Potato
{
    private string _Name;
    private uint _Weight;
    public string Name
    {   set { _Name = value; }
        get { return _Name; }
    }
    public uint Weight
    {
        set { _Weight = value; }
        get { return _Weight; }
    }
    public Potato(uint weight, string name)
    {
        _Weight = weight;
        _Name = name;
    }
}
torrho
  • 1,823
  • 4
  • 16
  • 21

1 Answers1

2

The easiest way is to do:

public IEnumerator GetEnumerator()
{
    return Items.GetEnumerator();
}

Or, if you only want the values:

public IEnumerator GetEnumerator()
{
    return Items.Values.GetEnumerator();
}

Don't forget to use a custom comparer for your dictionary:

 private Dictionary<object[], object> Items = new Dictionary<object[], object>(new ObjectArrayComparer());

With:

public class ObjectArrayComparer : IEqualityComparer<object[]>
{
    // Determines whether x and y are equal or not
    public bool Equals(object[] x, object[] y)
    {
        return object.ReferenceEquals(x, y) // Returns true if they are the same array instance
            || (x != null && y != null && x.SequenceEqual(y));  // Returns true if x and y are not null and have the same elements (order dependent)
    }

    // Function that allow to fastly determine if an element is in a set of not.        
    // This function must have the following property:
    //   x.Equals(y) implies GetHashCode(x) == GetHashCode(y)
    public int GetHashCode(object[] obj)
    {
        if (obj == null)
            return 0;

        // Unchecked sum of the Hash Codes of all elements in obj
        return unchecked(obj.Select(o => o != null ? o.GetHashCode() : 0).Aggregate(0, (a, b) => a + b));
    }
}

Why?

Try this:

var a = new int[] { 0 };
var b = new int[] { 0 };
Console.WriteLine(a == b);  // Returns false

Because the default comparer on an array is a reference comparison. As a and b are two instances of int[], they have not the same reference.

To change this behavior, you have to specify in the dictionary, how you want to compare the object[].

Cédric Bignon
  • 12,892
  • 3
  • 39
  • 51
  • I got an overflow exception at return obj.Sum(o => o.GetHashCode()); Something about divide by zero when the debugger tries to run Pile["String",P] = "Strung"; – torrho Jan 31 '13 at 17:15
  • @torrho It's fixed. It is because the _Sum_ method checks for overflow but it is not needed in this case. – Cédric Bignon Jan 31 '13 at 17:22
  • Thank you very much, that is an excellent solution! Implementation was well out of the scope of what I had imagined and beyond my coding ability. – torrho Jan 31 '13 at 17:26
  • @torrho If anything is still not clear for you, don't hesitate to ask me. – Cédric Bignon Jan 31 '13 at 17:27
  • @CédricBignon: to be safe you should check if `o` is different from null before calling `o.GetHashCode` – digEmAll Jan 31 '13 at 17:27
  • @CédricBignon What is GetHashCode()? – torrho Jan 31 '13 at 17:30
  • @CédricBignon nevermind, I think this [StackOverflow Post](http://stackoverflow.com/questions/462451/gethashcode-guidelines-in-c-sharp) clears things up for me. I understand hashing very well. I'm just not entirely familiar with hashing outside of the cryptographic sense. – torrho Jan 31 '13 at 17:37
  • @torrho I've added a comment on it. – Cédric Bignon Jan 31 '13 at 17:38