1

I've got a dictionary, i need to return the tvalue based on the search from a string array.

How do I return the tvalue for the tkey matching the string i'm searching for and the tvalue for the entry directly after it (to calculate the length of the entry.... this is so I can then access the original file and import the data).

parameters = a string array to be found.

The dictionary (dict) is setup as tkey = name, tvalue = bytes from the start of the file.

input 2 is the file with all the info in it.

        foreach (var p in parameters)
        {
            if (dict.ContainsKey(p))
            {
                int posstart = //tvalue of the parameter found;
                int posfinish = //tvalue ofnext entry ;

                using (FileStream fs = new FileStream(input[2], FileMode.Open, FileAccess.Read))
                {
                    byte[] bytes = //posstart to pos finish
                    System.Console.WriteLine(Encoding.Default.GetString(bytes));
                }
            }
            else
            {
                Console.WriteLine($"error, {p} not found");
            }
        }

Any help is welcomed, Thank you in advanced.

Cat
  • 31
  • 3
  • Possible duplicate of [get dictionary value by key](https://stackoverflow.com/questions/12169443/get-dictionary-value-by-key) – TAHA SULTAN TEMURI Oct 07 '19 at 19:01
  • Are you trying to get the value associated with the key from the dictionary? In C# dictionaries are indexed with `dict[key]`; is that what you're looking for? Also, you say "the next entry" but dictionaries in C# are not ordered; there is no "next" entry. Can you more clearly say what you mean by "next entry" here? It sounds like you have the wrong information in your dictionary; it sounds like you need a "start, finish" pair, not just the start. (C# has a sorted dictionary but it sorts on the key, not value.) – Eric Lippert Oct 07 '19 at 19:02
  • And what does it mean by `tvalue of next entry`? C# `Dictionary` doesn't necessarily preserve order, so for a 'next' to be meaningful you must sort it first based on some criteria. – Sach Oct 07 '19 at 19:06
  • By next entry I mean the entry directly after it, in the order that it was put into the dictionary. i'm trying to return the position of the entry and its length to import the data from the file using an index of the entries and their offset from the start. I want to find chandler and his info So "chandler" starts at offset "545" bytes from the start of the file. the tkey is "chandler" and the tvalue is "545" the next entry is "Joey" with an offset of "884" I need to return all bytes between 545 and 884 – Cat Oct 07 '19 at 19:10
  • if I had to order it i would order it ascending of the tvalue, is there a way to ensure that the dictionary is that? – Cat Oct 07 '19 at 19:12
  • "...the entry directly after it, in the order that it was put into the dictionary" The order items were added isn't retained by the dictionary. It's not possible. You can use an [OrderedDictionary](https://learn.microsoft.com/en-us/dotnet/api/system.collections.specialized.ordereddictionary?view=netframework-4.8) for that though. – itsme86 Oct 07 '19 at 19:12

1 Answers1

3

The key problem here is this comment:

// tvalue of next entry

In C# dictionaries are not ordered, so there is no "next entry". (A SortedDictionary sorts on key, not value, so that's no help to you. An OrderedDictionary might be what you want, but let's assume that you have a Dictionary in hand and solve the problem from that point.)

Let's transform your unsorted name -> offset data structure into a better data structure.

Suppose we start with this:

    // name -> offset
    var dict = new Dictionary<string, int>() { 
      { "foo", 100 }, { "bar", 40 }, { "blah", 200 } };

We'll sort the dictionary by value and put the offsets into this sorted list:

    // index -> offset
    var list = new List<int>();

And then we'll make a new dictionary that maps names to indexes into this list:

    // name -> index
    var newDict = new Dictionary<string, int>();

Let's build the list and new dictionary from the old one:

    foreach (var pair in dict.OrderBy(pair => pair.Value))
    {
        newDict[pair.Key] = list.Count;
        list.Add(pair.Value);
    }

We also need the offset of the last byte as the last thing in the list:

    list.Add(theOffsetOfTheLastByte);

And now we can do a two-step lookup to get the offset and the next offset. First we look up the index by name, and then the offset by index:

    int fooIndex = newDict["foo"]; // 1
    int fooOffset = list[fooIndex]; // 100
    int nextIndex = fooIndex + 1;
    int nextOffset = list[nextIndex]; // 200

Make sense?

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • 2
    Note that if you had this sort of problem in production code, you'd probably want to wrap this solution in a class containing private collection members. Here is [an example](https://stackoverflow.com/a/10966684/18192) of this concept. – Brian Oct 07 '19 at 19:30
  • 1
    @Brian: That's a great point. If you have a problem that is solved by two data structures working together, like a list and a dictionary, then make a third data structure that encapsulates the functionality you need. – Eric Lippert Oct 07 '19 at 19:35
  • Good answer Eric! – Chris Catignani Oct 08 '19 at 00:32