Archive for April, 2008

XML Makes A Bad Dictionary Key

Tuesday, April 29th, 2008

If you've ever tried to use the result of an E4X expression as a Dictionary key, you're probably no stranger to frustration. Mine started when I traced a problem I was having back to the following code:

import flash.utils.Dictionary;
var myXML:XML = <a><b /></a>;
var myDictionary:Dictionary = new Dictionary();
myDictionary[myXML.b[0]] = 'hello world';
trace(myDictionary[myXML.b[0]]);

If you're like I was, you're probably expecting this to trace "hello world". Instead, I got "undefined". So what's going on here? A glance at the documentation for the Dictionary class tells us that Dictionary "uses strict equality (===) for key comparison on non-primitive object keys." XML is a non-primitive, so logic dictates that myXML.b[0] !== myXML.b[0]! I guess this isn't completely preposterous: perhaps the dot operator returns a copy of the node? It's simple enough to check. I typed in the following.

var myXML:XML = <a><b /></a>;
trace(myXML.b[0] === myXML.b[0]);

true. Clearly, something strange is going on here. If Dictionary is indeed using strict equality, as it claims, then my initial code should've traced "hello world." On the other hand, maybe the strict equality operator is lying?

A Solution?

Since the strict equality operator returns the value we expect, we can find the value that corresponds to our key simply by iterating through the Dictionary with a function like the following:

function getDictionaryValue(dict:Dictionary, key:Object):Object
{
	var value:Object;
	
	if ((key is XML) && (dict[key] == undefined))
	{
		// Iterate through the dictionary to find a matching key.
		for (var k:Object in dict)
		{
			if (k === key)
			{
				value = dict[k];
				break;
			}
		}
	}
	else
	{
		value = dict[key];
	}
	return value;
}

Passing your Dictionary and key to the getDictionaryValue function will return the value you expected from the beginning.