2

I have the following piece of code

public Dictionary<int[], string> worldMap = new Dictionary<int[], string>();

for (int x=0; x <= 10; x++) {
    for (int y=0; y <= 10; y++) {
        int[] cords = new int[]{x,y};
        worldMap.Add(cords, "empty");          
    }
}

How do I get values from this dictionary?

John K
  • 55
  • 7

5 Answers5

1

You can iterate over the entire dictionary.

foreach (var map in worldMap)
{
    Console.WriteLine(String.Join(", ", map.Key) + " - " + map.Value);
}

Or look it up by reference

Dictionary<int[], string> worldMap = new Dictionary<int[], string>();

for (int x = 0; x <= 10; x++)
{
    for (int y = 0; y <= 10; y++)
    {
        int[] cords = new int[] { x, y };
        worldMap.Add(cords, "empty");

        Console.WriteLine(worldMap[cords]);
    }
}

When you use an array or class, the dictionary uses the reference to the object in the background. This makes some things impossible. For instance if you new another list with the same values, the dictionary will throw an exception saying the key is not found.

Dictionary<int[], string> worldMap = new Dictionary<int[], string>();

for (int x = 0; x <= 10; x++)
{
    for (int y = 0; y <= 10; y++)
    {
        int[] cords = new int[] { x, y };
        worldMap.Add(cords, "empty");

        //This will cause an exception
        Console.WriteLine(worldMap[new int[] { x, y }]);
    }
}
Nathan
  • 1,437
  • 12
  • 15
  • It's not totally true about using classes - you can use a class that has correctly overridden `GetHashCode` & `Equals`, and so long as the hash code does change, i.e. read-only object. That's how the class `String` works. So too anonymous classes. – Enigmativity Jul 07 '15 at 04:23
1

Create an IEqualityComparer and define your dictionary using that. you can find sample code in below SO question:

An integer array as a key for Dictionary

Community
  • 1
  • 1
Damith
  • 62,401
  • 13
  • 102
  • 153
1

Consider using System.Drawing.Point instead of an int array. In general, Dictionaries will only match if it's the exact same object that went into it. Even another object with the same value won't work.

But some data types such as Point are different, and implement all the hashing and equality check features necessary to be used a keys in a dictionary.

Dwedit
  • 618
  • 5
  • 11
0

After you populate the worldMap you can get your keys like this (You have to add using System.Linq):

List<int[]> coords = worldMap.Keys.ToList();

Then you can get any value from the coords List like this (Make sure you use a value within the bounds of your List):

worldMap[coords[0]]

Code Sample:

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    public static void Main()
    {
        Dictionary<int[], string> worldMap = new Dictionary<int[], string>();
        for (int x = 0; x <= 10; x++)
        {
            for (int y = 0; y <= 10; y++)
            {
                int[] cords = new int[] { x, y };
                worldMap.Add(cords, String.Format("empty{0}_{1}", x, y));
            }
        }
        // This should have 121 coordinates from (0, 0) to (10, 10)
        List<int[]> coords = worldMap.Keys.ToList();
        Console.WriteLine(worldMap[coords[21]]);
    }
}

Demo

Shar1er80
  • 9,001
  • 2
  • 20
  • 29
0

The use of an int[] for your word map coordinates is a poor choice for a number of reasons, not least of which I could send through zero, one, three, or more values when it seems like you specifically are using only two.

You would be far better off creating you own read-only class to hold your coordinates instead.

Try this class:

public sealed class WorldMapCoord : IEquatable<WorldMapCoord>
{
    private readonly int _X; 
    private readonly int _Y;

    public int X { get { return _X; } } 
    public int Y { get { return _Y; } }

    public WorldMapCoord(int X, int Y)
    {
        _X = X; 
        _Y = Y;    
    }

    public override bool Equals(object obj)
    {
        if (obj is WorldMapCoord)
                return Equals((WorldMapCoord)obj);
        return false;
    }

    public bool Equals(WorldMapCoord obj)
    {
        if (obj == null) return false;
        if (!EqualityComparer<int>.Default.Equals(_X, obj._X)) return false; 
        if (!EqualityComparer<int>.Default.Equals(_Y, obj._Y)) return false;    
        return true;
    }

    public override int GetHashCode()
    {
        int hash = 0;
        hash ^= EqualityComparer<int>.Default.GetHashCode(_X); 
        hash ^= EqualityComparer<int>.Default.GetHashCode(_Y);
        return hash;
    }

    public override string ToString()
    {
        return String.Format("{{ X = {0}, Y = {1} }}", _X, _Y);
    }
}

Now your code would look like this:

public Dictionary<WorldMapCoord, string> worldMap = new Dictionary<WorldMapCoord, string>();

for (int x=0; x <= 10; x++)
{
    for (int y=0; y <= 10; y++)
    {
        worldMap.Add(new WorldMapCoord(x, y), "empty");          
    }
}

Since the class is read-only, and it implements GetHashCode & Equals you can use this code to retrieve values from the dictionary:

for (int x=0; x <= 10; x++)
{
    for (int y=0; y <= 10; y++)
    {
        string value = worldMap[new WorldMapCoord(x, y)];
    }
}
Enigmativity
  • 113,464
  • 11
  • 89
  • 172