3-D String Array (or better alternative?)

  • Thread starter Thread starter Doug
  • Start date Start date
D

Doug

I have data that looks something like this when returned from a stored
procedure (3 columns, X rows):

Key1 Name1 Value1
Key1 Name2 Value2
Key1 Name3 Value3
Key1 Name4 Value4
Key2 Name1 Value1
Key2 Name2 Value2
Key3 Name1 Value1
KeyX NameY ValueY

Data type for all is string.
Number of rows returned from sp will never exceed 100.

You can see that there is a conceptual 1:many relationship between Keys and
Names; and a 1:1 relationship between Names and Values.

Order for Key, Name, or Value is unimportant to my application logic - so
could be returned from db sorted by alpha if necessary.

My application logic needs to (1) quickly find all of the Name/Value pairs
for a given key; and (2) update specific Value values (sorry!). Eventually
all the updated Value values will be written back to the database (i.e.,
Keys and Names will never be updated) The application logic will never add
or remove Keys, Names, or Values. We're only reading lists of Name/Value
pairs, and updating Value values.

I would prefer to *not* store this in an in-memory ADO.NET DataTable for
performance and size reasons.

I'm thinking a 3-dimensional array might give me best performance - but I
don't know the syntax required to populate it or to retrieve and update its
data. I could look it up, but don't know if doing that would yield the best
performance.

Recommendations? Suggestions? (syntax examples, if possible, would be very
much appreciated).

Thank You!
 
You can do this with 2 System.Collections.Hashtable(s) ala:

HashTable<key, hashTable>
HashTable<name, value>

1st table holds key values and references to name/value pair hash for each key... FYI .NET configuration file info is stored in memory in Hashtables as string keys with to object or Hashtable values; Hashtable values store string keys with object or Hashtable values, and so on, and so on...

--OR--

You can take advantage of 1:1 between Name & Value and use only 1 hashtable ala:

HashTable<key + name, value> keyNameValuePairs;

When inserting into Hash literally use "key + name" as the key. Substring can be used to seperate "key + name" back into 2 pieces if needed.

--Richard
 
Doug said:
I have data that looks something like this when returned from a stored
procedure (3 columns, X rows):

Key1 Name1 Value1
Key1 Name2 Value2
Key1 Name3 Value3
Key1 Name4 Value4
Key2 Name1 Value1
Key2 Name2 Value2
Key3 Name1 Value1
KeyX NameY ValueY

Data type for all is string.
Number of rows returned from sp will never exceed 100.
....
I would prefer to *not* store this in an in-memory ADO.NET DataTable for
performance and size reasons.

....

These two statements are inconsistent. With fewer than 100 rows, you can
have no valid objection to using a DataTable.

That being said you could load these items into a hashtable. The key here
is that the hashtable entries would be collections. SOmething like this:


Hashtable ht = new Hashtable();
IDictionary keyItems;
if (!ht.Contains(keyName))
{
keyItems = new System.Collections.Specialized.ListDictionary();
ht.Add(keyName,keyItems);
}
else
{
keyItems = (IDictionary) ht[keyName];
}
keyItems.Add(name,value);


Here using a Hashtable for the outer dictionary and a linked list for the
inner one.

David
 
<<With fewer than 100 rows, you can have no valid objection to using a
DataTable>>

There might be this objection given the context in which this thing will be
used: The context is that this structure (whatever I end up with) will exist
in an ASP.NET Web Application Session state. So, start multiplying the
"fewer than 100 rows" by the number of Sessions and suddenly size matters
more and more as the number of Sessions increases.

Perhaps I'm still wrong though. The unnecessary size I'm thinking of is the
XML involved in storing this as a DataTable (I haven't measured the bytes
involved, but we all know XML is verbose - more so than a 3d array or
Hashtable - and DataTables are XML structures.).

Thanks for the sample code on the Hashtable.
 
Not sure why it hasn't been offered but the HybridDictionary is a great space
saving device that switches from using an internal array and linear look-up to
using a Hashtable at a predefined performance tuned size. The class was
specifically built to improve performance of look-up and memory usage when
using lightly populated collections of name/value pairs. In context this would
automatically switch you to the most performant method depending on the
numbers of records rather than requiring large amounts of code.

To speak in the defense of the DataSet, it doesn't use XML until you serialize
it. You aren't wasting memory by using a DataSet at all. There is some small
extra overhead in using it because of extra properties about the data that are
stored but in general all you have is:

A DataSet, and you don't even have that unless you want one.
A DataTable - DataColumnCollection and DataRowCollection
DataColumnCollection - Consists of DataColumn's one for each
DataRowCollection - Consists of DataRow's one for each row

DataRow - int's that offset into DataStorage. Doesn't store values
DataColumn - Information about the actual column + a DataStorage element
that allows indexing by the DataRow into the internal storage.
StringStorage is the DataStorage override used and it has a string[] backing
store.
 
A 1:many relationship between Keys and Values? Then you cannot use a
Hasthtable or HybridDictionary. A key needs to reference one and only one
value, and it must be unique in the collection (no duplicates as in your
example data).

For 100 entries use a DataTable. You can then use the DefaultView to Filter
and/or Find the rows you need.

kevin aubuchon
 
Kevin Aubuchon said:
A 1:many relationship between Keys and Values? Then you cannot use a
Hasthtable or HybridDictionary. A key needs to reference one and only one
value, and it must be unique in the collection (no duplicates as in your
example data).

There's nothing to stop you from using Hashtable even so - just make
the value set in the hashtable be a reference to an ArrayList
containing all the entries for that key.
 
Jon Skeet said:
There's nothing to stop you from using Hashtable even so - just make
the value set in the hashtable be a reference to an ArrayList
containing all the entries for that key.

I understand that you can create a hashtable with a value set to be
referencing an ArrayList but I'm unsure of how you would go about
coding this. I'm new to C# but have had vast experience doing this
via Perl. Could you provide a small sample?
 
Jason Kumpf said:
I understand that you can create a hashtable with a value set to be
referencing an ArrayList but I'm unsure of how you would go about
coding this. I'm new to C# but have had vast experience doing this
via Perl. Could you provide a small sample?

Sure. Assume a class already has a hashtable set up appropriately. The
following adds a value:

void AddValue (string key, string value)
{
ArrayList list = (ArrayList) table[key];

if (list==null)
{
list = new ArrayList();
table[key] = list;
}

list.Add(value);
}
 
Jon Skeet said:
There's nothing to stop you from using Hashtable even so - just make
the value set in the hashtable be a reference to an ArrayList
containing all the entries for that key.

I understand that you can create a hashtable with a value set to be
referencing an ArrayList but I'm unsure of how you would go about
coding this. I'm new to C# but have had vast experience doing this
via Perl. Could you provide a small sample?
 
Back
Top