34

I have a List<MyClass> MyList where

public class MyClass
{
    public string name { get; set; }
    public string value { get; set; }
}

Given a name, I'd like to get the corresponding value. I have it currently implemented as:

MyList[MyList.FindIndex(item => String.Compare(item.name, "foo", 0) == 0)].value

Is there a cleaner way to do this?

Hossein Narimani Rad
  • 31,361
  • 18
  • 86
  • 116
RaGe
  • 22,696
  • 11
  • 72
  • 104
  • 2
    Possible duplicate of *[How can I find a specific element in a List?](http://stackoverflow.com/questions/9854917/how-can-i-find-a-specific-element-in-a-listt)*. – Peter Mortensen Oct 19 '16 at 16:57

6 Answers6

102

Either use LINQ:

var value = MyList.First(item => item.name == "foo").value;

(This will just find the first match, of course. There are lots of options around this.)

Or use Find instead of FindIndex:

var value = MyList.Find(item => item.name == "foo").value;

I'd strongly suggest using LINQ though - it's a much more idiomatic approach these days.

(I'd also suggest following the .NET naming conventions.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 5
    Don't forget to check for nulls before calling `.value` – banging Apr 23 '13 at 19:08
  • 2
    @banging: I was trying to write something which had the same assumptions that the original code did - the original code would go bang if the value wasn't found, so this does too. – Jon Skeet Apr 23 '13 at 19:13
  • Ty. When you say .net naming convention, did you mean not capitalizing the starting letters of object names? ( **M**yList vs myList) or something else? – RaGe Apr 23 '13 at 19:14
  • 2
    @RaGe: I was more talking about the properties. But if `MyList` isn't a property or a constant, it should probably be `myList`, yes. Not that I'm ever keen on `my` as a prefix for names. – Jon Skeet Apr 23 '13 at 19:17
  • @JonSkeet Sorry Jon, that note was not really for you but a general reminder for people learning ;) – banging Apr 23 '13 at 19:30
  • @JonSkeet How do I use LINQ in visual studio against my List<> ? Only non-linq methods appear, FindIndex in this case. – guiomie Jan 14 '14 at 20:53
  • 1
    @guiomie: Make sure you have a using directive for System.Linq. – Jon Skeet Jan 14 '14 at 22:36
13

You can use the Where to filter and Select to get the desired value.

MyList.Where(i=>i.name == yourName).Select(j=>j.value);
Hossein Narimani Rad
  • 31,361
  • 18
  • 86
  • 116
  • I just refreshed and Skeet's answer said "4 mins ago" while Hosseins said "3 mins ago"... and now they are both at 4. I'll call it a tie (they both didn't know the other was answering) – Cemafor Apr 23 '13 at 19:11
  • and all the comments on this answer are disappearing – Cemafor Apr 23 '13 at 19:12
  • @Cemafor: I saw that Hossein was answering, but I've given a slightly different answer - because it only finds *one* value. (That's all that's been indicated as a requirement.) – Jon Skeet Apr 23 '13 at 19:14
  • @JonSkeet: I'm not sure if you saw, but there was a converstion in the comments about the relative timing of your and Hossein's answers. And you are (of course) correct, your answer is more of a passive in place switch then Hossein's, whos would return all matches. – Cemafor Apr 23 '13 at 19:23
  • 1
    @Cemafor: I didn't see the comments - just yours. I was just trying to explain that *similar* but distinct answers are possible even with awareness of each other :) – Jon Skeet Apr 23 '13 at 19:27
  • Shouldn't the "=" be "=="? – B. Clay Shannon-B. Crow Raven Feb 11 '16 at 05:45
6

I would use .Equals() for comparison instead of ==.

Like so:

MyClass item = MyList.Find(item => item.name.Equals("foo"));

Particularly because it gives you options like StringComparison, which is awesome. Example:

MyClass item = MyList.Find(item => item.name.Equals("foo", StringComparison.InvariantCultureIgnoreCase);

This enables your code to ignore special characters, upper and lower case. There are more options.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
rasmus91
  • 3,024
  • 3
  • 20
  • 32
5

Using function Find is cleaner way.

MyClass item = MyList.Find(item => item.name == "foo");
if (item != null) // check item isn't null
{
 ....
}
misak
  • 342
  • 1
  • 2
  • 13
3

Enumerable.First returns the element instead of an index. In both cases you will get an exception if no matching element appears in the list (your original code will throw an IndexOutOfBoundsException when you try to get the item at index -1, but First will throw an InvalidOperationException).

MyList.First(item => string.Equals("foo", item.name)).value
Sam Harwell
  • 97,721
  • 20
  • 209
  • 280
-2

hi body very late but i am writing

if(mylist.contains(value)){}

  • Welcome to Stack Overflow! It's unclear how this answers the question. Please review https://stackoverflow.com/help/how-to-answer. – stephenwade Apr 04 '20 at 16:26
  • 1
    I could only see the answer. Sorry, I removed it so to not confuse anyone. All I could see was the comment and didnt see any of the tags or details on the question so I had to make some assumptions. I removed it – DavidG Apr 07 '20 at 13:11