Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Better Way to Search for a Value in a List of KeyValuePairs???

Better Way to Search for a Value in a List of KeyValuePairs???

Scheduled Pinned Locked Moved C#
csharplinqquestion
16 Posts 11 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • N Offline
    N Offline
    NickPace
    wrote on last edited by
    #1

    I have a list of KeyValuePairs:

    List<KeyValuePair<Guid, string>> someList;

    (And it is populated with several hundred KeyValuePairs of Guids and strings.) I want to determine if this list of KeyValuePairs contains a certain string value as part of its values. One way to do this is to loop through each KeyValuePair as follows:

    bool onList = false;

    foreach (KeyValuePair<Guid, string> kvp in someList)
    {
    if (kvp.Value.Equals(someStringValue))
    {
    onList = true;
    break;
    }
    }

    if (onList)
    {
    // Do something...
    }

    However, this seems like a clunky way to perform this check. It seems to me that there must be a way to use the ‘Contains’ method of the List object or Linq to perform this check, but I can’t seem to get the semantics right. Perhaps something like:

    var someValue = someList.Where(kvp => kvp.Value.Equals(someStringValue)); // which doesn’t work

    Any suggestions?

    -NP Never underestimate the creativity of the end-user.

    E P D A I 8 Replies Last reply
    0
    • N NickPace

      I have a list of KeyValuePairs:

      List<KeyValuePair<Guid, string>> someList;

      (And it is populated with several hundred KeyValuePairs of Guids and strings.) I want to determine if this list of KeyValuePairs contains a certain string value as part of its values. One way to do this is to loop through each KeyValuePair as follows:

      bool onList = false;

      foreach (KeyValuePair<Guid, string> kvp in someList)
      {
      if (kvp.Value.Equals(someStringValue))
      {
      onList = true;
      break;
      }
      }

      if (onList)
      {
      // Do something...
      }

      However, this seems like a clunky way to perform this check. It seems to me that there must be a way to use the ‘Contains’ method of the List object or Linq to perform this check, but I can’t seem to get the semantics right. Perhaps something like:

      var someValue = someList.Where(kvp => kvp.Value.Equals(someStringValue)); // which doesn’t work

      Any suggestions?

      -NP Never underestimate the creativity of the end-user.

      E Offline
      E Offline
      Ennis Ray Lynch Jr
      wrote on last edited by
      #2

      HashTable

      Need custom software developed? I do custom programming based primarily on MS tools with an emphasis on C# development and consulting. I also do Android Programming as I find it a refreshing break from the MS. "And they, since they Were not the one dead, turned to their affairs" -- Robert Frost

      B 1 Reply Last reply
      0
      • N NickPace

        I have a list of KeyValuePairs:

        List<KeyValuePair<Guid, string>> someList;

        (And it is populated with several hundred KeyValuePairs of Guids and strings.) I want to determine if this list of KeyValuePairs contains a certain string value as part of its values. One way to do this is to loop through each KeyValuePair as follows:

        bool onList = false;

        foreach (KeyValuePair<Guid, string> kvp in someList)
        {
        if (kvp.Value.Equals(someStringValue))
        {
        onList = true;
        break;
        }
        }

        if (onList)
        {
        // Do something...
        }

        However, this seems like a clunky way to perform this check. It seems to me that there must be a way to use the ‘Contains’ method of the List object or Linq to perform this check, but I can’t seem to get the semantics right. Perhaps something like:

        var someValue = someList.Where(kvp => kvp.Value.Equals(someStringValue)); // which doesn’t work

        Any suggestions?

        -NP Never underestimate the creativity of the end-user.

        P Offline
        P Offline
        Pete OHanlon
        wrote on last edited by
        #3

        In essence you are mirroring a Dictionary here. Why not just use that instead?

        Forgive your enemies - it messes with their heads

        My blog | My articles | MoXAML PowerToys | Mole 2010 - debugging made easier - my favourite utility

        1 Reply Last reply
        0
        • N NickPace

          I have a list of KeyValuePairs:

          List<KeyValuePair<Guid, string>> someList;

          (And it is populated with several hundred KeyValuePairs of Guids and strings.) I want to determine if this list of KeyValuePairs contains a certain string value as part of its values. One way to do this is to loop through each KeyValuePair as follows:

          bool onList = false;

          foreach (KeyValuePair<Guid, string> kvp in someList)
          {
          if (kvp.Value.Equals(someStringValue))
          {
          onList = true;
          break;
          }
          }

          if (onList)
          {
          // Do something...
          }

          However, this seems like a clunky way to perform this check. It seems to me that there must be a way to use the ‘Contains’ method of the List object or Linq to perform this check, but I can’t seem to get the semantics right. Perhaps something like:

          var someValue = someList.Where(kvp => kvp.Value.Equals(someStringValue)); // which doesn’t work

          Any suggestions?

          -NP Never underestimate the creativity of the end-user.

          D Offline
          D Offline
          Dan Mos
          wrote on last edited by
          #4

          NickPace wrote:

          var someValue = someList.Where(kvp => kvp.Value.Equals(someStringValue)); // which doesn’t work

          Not sure if it is a typo but you don't select anything in the line below

          var someValue = someList.Where(kvp => kvp.Value.Equals(someStringValue)); // which doesn’t work

          It should be something like:

          var someValue = someList.Where(kvp => kvp.Value.Equals(someStringValue)).Select(kvp=>kvp).FirstOrDefault();

          Than you could check if it exits simply by comparing someValue.Value with string.Empty. If not found the FirstOrDefault() method will initialize it with the default values witch is string.Empty for strings. But there are more speedier approaches to this such as Dictionary, HashTable...

          All the best, Dan

          N M 2 Replies Last reply
          0
          • N NickPace

            I have a list of KeyValuePairs:

            List<KeyValuePair<Guid, string>> someList;

            (And it is populated with several hundred KeyValuePairs of Guids and strings.) I want to determine if this list of KeyValuePairs contains a certain string value as part of its values. One way to do this is to loop through each KeyValuePair as follows:

            bool onList = false;

            foreach (KeyValuePair<Guid, string> kvp in someList)
            {
            if (kvp.Value.Equals(someStringValue))
            {
            onList = true;
            break;
            }
            }

            if (onList)
            {
            // Do something...
            }

            However, this seems like a clunky way to perform this check. It seems to me that there must be a way to use the ‘Contains’ method of the List object or Linq to perform this check, but I can’t seem to get the semantics right. Perhaps something like:

            var someValue = someList.Where(kvp => kvp.Value.Equals(someStringValue)); // which doesn’t work

            Any suggestions?

            -NP Never underestimate the creativity of the end-user.

            A Offline
            A Offline
            Abhinav S
            wrote on last edited by
            #5

            You can always use LINQ. If you want to search by the GUID (key) make your search criteria GUID. IEnumerable result = someList.Where(y=>y.Key.Contains(searchGUID)); You can always search on the value as below. IEnumerable result = someList.Where(y=>y.Value.Contains(searchString)); In both cases, result will contain the final search result. Note that performance may or may not be better than using a loop. LINQ makes it easier to write code, performance is generally better (but not always).

            Too much of heaven can bring you underground Heaven can always turn around Too much of heaven, our life is all hell bound Heaven, the kill that makes no sound

            1 Reply Last reply
            0
            • D Dan Mos

              NickPace wrote:

              var someValue = someList.Where(kvp => kvp.Value.Equals(someStringValue)); // which doesn’t work

              Not sure if it is a typo but you don't select anything in the line below

              var someValue = someList.Where(kvp => kvp.Value.Equals(someStringValue)); // which doesn’t work

              It should be something like:

              var someValue = someList.Where(kvp => kvp.Value.Equals(someStringValue)).Select(kvp=>kvp).FirstOrDefault();

              Than you could check if it exits simply by comparing someValue.Value with string.Empty. If not found the FirstOrDefault() method will initialize it with the default values witch is string.Empty for strings. But there are more speedier approaches to this such as Dictionary, HashTable...

              All the best, Dan

              N Offline
              N Offline
              NickPace
              wrote on last edited by
              #6

              That works good, except I had to compare to null instead of a string because it returns a KeyValuePair object. But you got me on the right track. I guess I need to buy a good book on LINQ as I still struggle with it. And I agree that a Dictionary or HashTable would be better, but I'm stuck with the List that is passed to my method. Thanks again for your reply. It was very helpful.

              -NP Never underestimate the creativity of the end-user.

              M 1 Reply Last reply
              0
              • N NickPace

                I have a list of KeyValuePairs:

                List<KeyValuePair<Guid, string>> someList;

                (And it is populated with several hundred KeyValuePairs of Guids and strings.) I want to determine if this list of KeyValuePairs contains a certain string value as part of its values. One way to do this is to loop through each KeyValuePair as follows:

                bool onList = false;

                foreach (KeyValuePair<Guid, string> kvp in someList)
                {
                if (kvp.Value.Equals(someStringValue))
                {
                onList = true;
                break;
                }
                }

                if (onList)
                {
                // Do something...
                }

                However, this seems like a clunky way to perform this check. It seems to me that there must be a way to use the ‘Contains’ method of the List object or Linq to perform this check, but I can’t seem to get the semantics right. Perhaps something like:

                var someValue = someList.Where(kvp => kvp.Value.Equals(someStringValue)); // which doesn’t work

                Any suggestions?

                -NP Never underestimate the creativity of the end-user.

                I Offline
                I Offline
                Ian Shlasko
                wrote on last edited by
                #7

                If you want a replacement for Contains(), you don't need to use Where()... Any() means "If any member of the list satisfies this condition" (Opposite would be !All())

                bool onList = someList.Any(kvp => kvp.Value.Equals(someStringValue));

                Proud to have finally moved to the A-Ark. Which one are you in?
                Author of the Guardians Saga (Sci-Fi/Fantasy novels)

                1 Reply Last reply
                0
                • N NickPace

                  That works good, except I had to compare to null instead of a string because it returns a KeyValuePair object. But you got me on the right track. I guess I need to buy a good book on LINQ as I still struggle with it. And I agree that a Dictionary or HashTable would be better, but I'm stuck with the List that is passed to my method. Thanks again for your reply. It was very helpful.

                  -NP Never underestimate the creativity of the end-user.

                  M Offline
                  M Offline
                  Matt U
                  wrote on last edited by
                  #8

                  I am not sure I understand entirely. Why is it that you are stuck with the List?

                  djj55: Nice but may have a permission problem Pete O'Hanlon: He has my permission to run it.

                  N 1 Reply Last reply
                  0
                  • M Matt U

                    I am not sure I understand entirely. Why is it that you are stuck with the List?

                    djj55: Nice but may have a permission problem Pete O'Hanlon: He has my permission to run it.

                    N Offline
                    N Offline
                    NickPace
                    wrote on last edited by
                    #9

                    Short version: The company I work for, in their infinite wisdom, decided to outsource some of our code. The 'List' comes from the Data Access Layer that they coded and is used primarily as a datasource for comboboxes. And even though I have access to their code, I am not allowed to touch it...something about licensing, intellectual property, and the infinite wisdom of my company and some other political BS which I just don't care about anymore. I could ask them to code a Dictionary or HashTable for me, but I don't feel like it. So I basically do my best to work around the crap that is sent to me (which probably sounds familiar to most coders out there). The long version includes several pages of expletives. Use your imagination...

                    -NP Never underestimate the creativity of the end-user.

                    M 1 Reply Last reply
                    0
                    • N NickPace

                      Short version: The company I work for, in their infinite wisdom, decided to outsource some of our code. The 'List' comes from the Data Access Layer that they coded and is used primarily as a datasource for comboboxes. And even though I have access to their code, I am not allowed to touch it...something about licensing, intellectual property, and the infinite wisdom of my company and some other political BS which I just don't care about anymore. I could ask them to code a Dictionary or HashTable for me, but I don't feel like it. So I basically do my best to work around the crap that is sent to me (which probably sounds familiar to most coders out there). The long version includes several pages of expletives. Use your imagination...

                      -NP Never underestimate the creativity of the end-user.

                      M Offline
                      M Offline
                      Matt U
                      wrote on last edited by
                      #10

                      Haha, that sheds a whole new light on the situation. I though at first that you simply were not sure how to go about using a Dictionary, in which case I could have been of help. My apologies. Good luck with those non-coding, outsourced geniuses. ;P

                      djj55: Nice but may have a permission problem Pete O'Hanlon: He has my permission to run it.

                      1 Reply Last reply
                      0
                      • N NickPace

                        I have a list of KeyValuePairs:

                        List<KeyValuePair<Guid, string>> someList;

                        (And it is populated with several hundred KeyValuePairs of Guids and strings.) I want to determine if this list of KeyValuePairs contains a certain string value as part of its values. One way to do this is to loop through each KeyValuePair as follows:

                        bool onList = false;

                        foreach (KeyValuePair<Guid, string> kvp in someList)
                        {
                        if (kvp.Value.Equals(someStringValue))
                        {
                        onList = true;
                        break;
                        }
                        }

                        if (onList)
                        {
                        // Do something...
                        }

                        However, this seems like a clunky way to perform this check. It seems to me that there must be a way to use the ‘Contains’ method of the List object or Linq to perform this check, but I can’t seem to get the semantics right. Perhaps something like:

                        var someValue = someList.Where(kvp => kvp.Value.Equals(someStringValue)); // which doesn’t work

                        Any suggestions?

                        -NP Never underestimate the creativity of the end-user.

                        P Offline
                        P Offline
                        PIEBALDconsult
                        wrote on last edited by
                        #11

                        If you have to do that frequently, you should probably reengineer the whole thing. Another way would be to define a specific class to hold the data and implement the Equals method.

                        1 Reply Last reply
                        0
                        • E Ennis Ray Lynch Jr

                          HashTable

                          Need custom software developed? I do custom programming based primarily on MS tools with an emphasis on C# development and consulting. I also do Android Programming as I find it a refreshing break from the MS. "And they, since they Were not the one dead, turned to their affairs" -- Robert Frost

                          B Offline
                          B Offline
                          BillWoodruff
                          wrote on last edited by
                          #12

                          Ennis, Please see my comment on this thread. thanks, Bill

                          "Is it a fact - or have I dreamt it - that, by means of electricity, the world of matter has become a great nerve, vibrating thousands of miles in a breathless point of time? Rather, the round globe is a vast head, a brain, instinct with intelligence!" - Nathanial Hawthorne, House of the Seven Gables

                          1 Reply Last reply
                          0
                          • N NickPace

                            I have a list of KeyValuePairs:

                            List<KeyValuePair<Guid, string>> someList;

                            (And it is populated with several hundred KeyValuePairs of Guids and strings.) I want to determine if this list of KeyValuePairs contains a certain string value as part of its values. One way to do this is to loop through each KeyValuePair as follows:

                            bool onList = false;

                            foreach (KeyValuePair<Guid, string> kvp in someList)
                            {
                            if (kvp.Value.Equals(someStringValue))
                            {
                            onList = true;
                            break;
                            }
                            }

                            if (onList)
                            {
                            // Do something...
                            }

                            However, this seems like a clunky way to perform this check. It seems to me that there must be a way to use the ‘Contains’ method of the List object or Linq to perform this check, but I can’t seem to get the semantics right. Perhaps something like:

                            var someValue = someList.Where(kvp => kvp.Value.Equals(someStringValue)); // which doesn’t work

                            Any suggestions?

                            -NP Never underestimate the creativity of the end-user.

                            M Offline
                            M Offline
                            Mehdi Gholam
                            wrote on last edited by
                            #13

                            Try this:

                            var result = someList.FindAll(delegate(KeyValuePair q) {return q.Value.Equals(someStringValue);});

                            You can use Find for single values also.

                            Its the man, not the machine - Chuck Yeager If at first you don't succeed... get a better publicist If the final destination is death, then we should enjoy every second of the journey.

                            1 Reply Last reply
                            0
                            • N NickPace

                              I have a list of KeyValuePairs:

                              List<KeyValuePair<Guid, string>> someList;

                              (And it is populated with several hundred KeyValuePairs of Guids and strings.) I want to determine if this list of KeyValuePairs contains a certain string value as part of its values. One way to do this is to loop through each KeyValuePair as follows:

                              bool onList = false;

                              foreach (KeyValuePair<Guid, string> kvp in someList)
                              {
                              if (kvp.Value.Equals(someStringValue))
                              {
                              onList = true;
                              break;
                              }
                              }

                              if (onList)
                              {
                              // Do something...
                              }

                              However, this seems like a clunky way to perform this check. It seems to me that there must be a way to use the ‘Contains’ method of the List object or Linq to perform this check, but I can’t seem to get the semantics right. Perhaps something like:

                              var someValue = someList.Where(kvp => kvp.Value.Equals(someStringValue)); // which doesn’t work

                              Any suggestions?

                              -NP Never underestimate the creativity of the end-user.

                              B Offline
                              B Offline
                              BillWoodruff
                              wrote on last edited by
                              #14

                              This is the kind of question and discussion I'd so enjoy seeing more of on this forum, thanks, Nick. It would be fascinating to know how the different techniques suggested here, including Ennis' suggestion of using a HashTable, compare in terms of speed and efficiency. This discussion on StackOverFlow may be relevant (?): [^] In this case we don't know whether every string in each KeyValuePair is unique or not, and that could influence the gamut of solutions ? Here's my suggestion, but I'm no Linq master:

                              List<KeyValuePair<Guid, string>> kvpList = new List<KeyValuePair<Guid, string>>();

                              private IEnumerable<string> sList;

                              private void testKVPToList()
                              {
                              for (int i = 1000; i < 2000; i++)
                              {
                              Guid guid = new Guid("F4168C51-CEB2-4EBC-B6BF-319B339D" + i.ToString());
                              kvpList.Add(new KeyValuePair<Guid, string>(guid,(i*5).ToString()));
                              }

                              sList = from kvp in kvpList select kvp.Value;
                              
                              if(sList.Contains("5000")) Console.WriteLine("5000 found");
                              if(sList.Contains("9995")) Console.WriteLine("9995 found");
                              

                              }

                              Whether 'tis better to take a 'one-time' hit and build a List, or to dynamically look-up on-the-fly: that's a good question ! And, if the goal is to build the fastest List to search ? My casual attempt to make a SortedList from a KeyValuePair List resulted in a pig that could not fly, but I'm sure there's a way :) I'd certainly go and examine Mehdi Gholam's recent 'Hoot' full-text search be-all-and-end-all project[^], and see what he's doing there, because I'll bet it's as optimized as possible. You can find some implementations of the Boyer-Moore algorithm here on CP:[^].

                              "Is it a fact - or have I dreamt it - that, by means of electricity, the world of matter has become a great nerve, vibrating thousands of miles in a breathless point of time? Rather, the round globe is a vast head, a brain, instinct with intelligence!" - Nathanial Hawthorne, House of the Seven Gables

                              modified on Thursday, September 8, 2011 2:45 AM

                              N 1 Reply Last reply
                              0
                              • B BillWoodruff

                                This is the kind of question and discussion I'd so enjoy seeing more of on this forum, thanks, Nick. It would be fascinating to know how the different techniques suggested here, including Ennis' suggestion of using a HashTable, compare in terms of speed and efficiency. This discussion on StackOverFlow may be relevant (?): [^] In this case we don't know whether every string in each KeyValuePair is unique or not, and that could influence the gamut of solutions ? Here's my suggestion, but I'm no Linq master:

                                List<KeyValuePair<Guid, string>> kvpList = new List<KeyValuePair<Guid, string>>();

                                private IEnumerable<string> sList;

                                private void testKVPToList()
                                {
                                for (int i = 1000; i < 2000; i++)
                                {
                                Guid guid = new Guid("F4168C51-CEB2-4EBC-B6BF-319B339D" + i.ToString());
                                kvpList.Add(new KeyValuePair<Guid, string>(guid,(i*5).ToString()));
                                }

                                sList = from kvp in kvpList select kvp.Value;
                                
                                if(sList.Contains("5000")) Console.WriteLine("5000 found");
                                if(sList.Contains("9995")) Console.WriteLine("9995 found");
                                

                                }

                                Whether 'tis better to take a 'one-time' hit and build a List, or to dynamically look-up on-the-fly: that's a good question ! And, if the goal is to build the fastest List to search ? My casual attempt to make a SortedList from a KeyValuePair List resulted in a pig that could not fly, but I'm sure there's a way :) I'd certainly go and examine Mehdi Gholam's recent 'Hoot' full-text search be-all-and-end-all project[^], and see what he's doing there, because I'll bet it's as optimized as possible. You can find some implementations of the Boyer-Moore algorithm here on CP:[^].

                                "Is it a fact - or have I dreamt it - that, by means of electricity, the world of matter has become a great nerve, vibrating thousands of miles in a breathless point of time? Rather, the round globe is a vast head, a brain, instinct with intelligence!" - Nathanial Hawthorne, House of the Seven Gables

                                modified on Thursday, September 8, 2011 2:45 AM

                                N Offline
                                N Offline
                                NickPace
                                wrote on last edited by
                                #15

                                Thanks! That's good information you provided. Overall I am pleasantly surprised and pleased with the responses to my initial questions. Everyone provided some good ideas and I even learned a couple new things concerning LINQ. This issue started out as a minor client-requested enhancement to one of their existing applications (hopefully just a one-time deal), and when I looked at the code in question I discovered the data I needed to compare against already existed in a List of KeyValuePairs, so really no need to query the database again. And thus my little quest began. When I saw the first response from Pete O'Hanlon, I thought: "Of course. I'll just cast the List to an equivalent Dictionary object and use its 'ContainsValue' method." Which I thought was going to work because it compiled just fine, but then threw an 'Invalid Cast' exception during runtime (same thing for a HashTable). :sigh: And so the quest continued... I eventually went with the answer provided by MDL=>Moshu. It works great. The List has about 2000 KeyValuePairs in it and the new search appears instantaneous to the end users. So though the code design may not be ideal, it works, it's stable, it performs well, and the client is happy. And that is what it is really all about.

                                -NP Never underestimate the creativity of the end-user.

                                1 Reply Last reply
                                0
                                • D Dan Mos

                                  NickPace wrote:

                                  var someValue = someList.Where(kvp => kvp.Value.Equals(someStringValue)); // which doesn’t work

                                  Not sure if it is a typo but you don't select anything in the line below

                                  var someValue = someList.Where(kvp => kvp.Value.Equals(someStringValue)); // which doesn’t work

                                  It should be something like:

                                  var someValue = someList.Where(kvp => kvp.Value.Equals(someStringValue)).Select(kvp=>kvp).FirstOrDefault();

                                  Than you could check if it exits simply by comparing someValue.Value with string.Empty. If not found the FirstOrDefault() method will initialize it with the default values witch is string.Empty for strings. But there are more speedier approaches to this such as Dictionary, HashTable...

                                  All the best, Dan

                                  M Offline
                                  M Offline
                                  MicroVirus
                                  wrote on last edited by
                                  #16

                                  Ok, might be a stupid question here, but ... Why doesn't the first line work? The someList.Where returns IEnumerable right? So, shouldn't someValue just be enumerable? I'm not sure what Select is doing there either. It transforms a kvp to a kvp, so doesn't that mean the entire Select is just removable?

                                  1 Reply Last reply
                                  0
                                  Reply
                                  • Reply as topic
                                  Log in to reply
                                  • Oldest to Newest
                                  • Newest to Oldest
                                  • Most Votes


                                  • Login

                                  • Don't have an account? Register

                                  • Login or register to search.
                                  • First post
                                    Last post
                                  0
                                  • Categories
                                  • Recent
                                  • Tags
                                  • Popular
                                  • World
                                  • Users
                                  • Groups