[.net] Implementing a MultiMap in C# (Solved)

Started by
1 comment, last by JimPrice 18 years, 11 months ago
Arrrgh! Now that's out of the way. I'm trying to implement a multimap in C# (VS 2003 version, not V2 with it's generics), as I do so miss some of the functionality of the STL. However, it seems to be going wrong. Here's some code, then I'll describe my problem. First the multimap itself:

using System;
using System.Collections;

namespace C_sharp_Console_Experimentation
{
	/// <summary>
	/// Summary description for MultiMap.
	/// </summary>
	public class MultiMap
	{

		public MultiMap()
		{
			//
			// TODO: Add constructor logic here
			//
		}

		public void InsertElement(object key, object inserter)
		{
			// Check to see if key already exists
			ArrayList elements = null;
			foreach(MultiMapPair mmp in multimap_)
			{
				if(key == mmp.key_)
				{
					elements = mmp.elements_;
					break;
				}
			}

			// If key already exists, add to the requisite group
			if(elements != null)
				elements.Add(inserter);

			// Else create a new pair and add
			else
			{
				MultiMapPair newPair = new MultiMapPair(key, inserter);
				multimap_.Add(newPair);
			}
		}

		// Get a list of elements associated with a given key
		public ArrayList WithKey(object key)
		{
			ArrayList elements = new ArrayList();

			// Check to see if key exists - if so, change elements
			foreach(MultiMapPair mmp in multimap_)
			{
				if(key == mmp.key_)
				{
					elements = mmp.elements_;
					break;
				}
			}
			return elements;
		}

		// Get a list of the keys used in the multimap
		public ArrayList Keys()
		{
			ArrayList keyArray = new ArrayList();
			foreach(MultiMapPair mmp in multimap_)
			{
				keyArray.Add(mmp.key_);
			}
			return keyArray;
		}

		#region Implementation Class


		private class MultiMapPair
		{
			public MultiMapPair(object key, object inserter)
			{
				key_ = key;
				elements_.Add(inserter);
			}
			public object key_;
			public ArrayList elements_ = new ArrayList();
		}


		#endregion Implementation Class


		#region Member Data

		// An arraylist of pairs
		private ArrayList multimap_ = new ArrayList();


		#endregion Member Data
	}
}



And now the test code:

using System;
using System.Data;
using System.IO;
using System.Collections;

namespace C_sharp_Console_Experimentation
{
	/// <summary>
	/// Summary description for Class1.
	/// </summary>
	class Class1
	{
		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main(string[] args)
		{
			//
			// TODO: Add code to start application here
			//

			MultiMap map = new MultiMap();

			map.InsertElement(1, "one1");

			ArrayList keys = map.Keys();
			foreach(object o in keys)
				Console.WriteLine(o.ToString());


			ArrayList elements = map.WithKey(1);
			foreach(object o in elements)
				Console.WriteLine(o.ToString());


			Console.Read();
		}
	}
}



The element insertion appears to work, and this is confirmed by the Keys function (although it does fail if I add more than one element with the same key, I suspect for the same reason as that I'm about to get to). The printing of all elements with key 1 doesn't appear to work however, in that it doesn't print anything. The code is failing on this section: foreach(MultiMapPair mmp in multimap_) { if(key == mmp.key_) In that the equality is never met - even though the debugger identifies the keys correctly (in that both key and mmp.key_ are identifed as system.int32 variables with value 1). I suspect the issue is to do with the casting to and from the object base class, but I'm not sure. Can anyone spot anything (or any other horrendous issues with the code, as I suspect there are). Thanks, Jim. [Edited by - JimPrice on May 23, 2005 7:33:15 PM]
Advertisement
Quote:Original post by JimPrice
The code is failing on this section:

foreach(MultiMapPair mmp in multimap_)
{
if(key == mmp.key_)

In that the equality is never met - even though the debugger identifies the keys correctly (in that both key and mmp.key_ are identifed as system.int32 variables with value 1).

I suspect the issue is to do with the casting to and from the object base class, but I'm not sure.


I am not entirely sure this is your problem, but you are probably comparing reference equality with the == which will be different for two different boxed integers, but may well work with reference types. Try using object.Equals instead of == for your equality test. Probably won't perform as good, but you may not be all that concerned with performance at this point.

EDIT: be careful of null values. If you allow them as keys you will have to text for that before you call Equals.
Thanks, works a treat.

I'd thought that might be the problem originally, but only changed Equals at one point (I'd forgotten I'd used == twice). Went back and checked it over and, sure-enough, it works.

Thanks again,
Jim.

This topic is closed to new replies.

Advertisement