Get index of an object in a Generic list

36,368

Solution 1

The method you want is FindIndex(Predicate)

int index = list.FindIndex(MiniMapRecord p => p.IDa == IDa.SystemID & p.IDb == pInputRecordMap.IDb);

Solution 2

As others have stated, there's no way to avoid looping through the items to find one unless you either:

Remember the indexes. When you create the list, save the relevant indexes to a member variable. This may not be appropriate for your problem.

Or:

Keep the list sorted and do a binary search for the item. This also may not work because you have two identifiers.

IndexOf() is a simple solution, but it will cost O(N) (linear).

Solution 3

You can use the IndexOf() method to get the index of a given element of your List<>.

However, note that since a linked list implies no random access, there really isn't any other way to find a specific element (and consequently its index) other than starting from the beginning and checking one element at a time.

Solution 4

Use the .IndexOf() method of the list to find the index, and then use .RemoveAt() to remove it.

Share:
36,368
user437631
Author by

user437631

Updated on June 13, 2021

Comments

  • user437631
    user437631 almost 3 years

    I have a list of custom objects with two properties as identifiers (IDa and IDb).

    Every time I remove an object I need to know its index. How do I get an index of an object without looping all the list?

    List<CustomObject> list = new List<CustomObject>();
    list.RemoveAll((MiniMapRecord p) => p.IDa == IDa.SystemID & p.IDb == pInputRecordMap.IDb);
    
  • Adam Houldsworth
    Adam Houldsworth about 13 years
    Of course, if you have the object to do IndexOf, you can just to Remove(obj).
  • user437631
    user437631 about 13 years
    not quite. it's a new instance with the same properties.IndexOf() is by refrence if i'm not mistaken.
  • jonsca
    jonsca about 13 years
    The OP didn't say anything about locating the object via the two properties. I was assuming the object was known.
  • user437631
    user437631 about 13 years
    isn't there a way without looping for all the list? i don't have the object only it's properties. it's a proccess that is getting thousands of records and for each record to find it in the list and remove it.
  • user437631
    user437631 about 13 years
    what is the complexity of it?
  • Josh G
    Josh G about 13 years
    If you only have the properties of the object, this is the way to go.
  • Josh G
    Josh G about 13 years
    Down-voting seems a little extreme here. It was not clear from the question that only the properties were known.
  • dandan78
    dandan78 about 13 years
    In that case I believe MattDavey has answered your question.
  • MattDavey
    MattDavey about 13 years
    It's worth pointing out that FindIndex is implemented internally with a for loop.
  • toannm
    toannm about 9 years
    How IndexOf() compare two different objects?
  • Josh G
    Josh G about 9 years
    IndexOf() uses the default EqualityComparer, so if you overload equality for your items you can control this. Otherwise you can use First() or Single() (from LINQ) and pass in a predicate to test / compare the objects. var match = items.Single(item => item.Id == myId);
  • toannm
    toannm about 9 years
    Thanks Josh G, but so what will happen if i didn't overload equality for my object?
  • Josh G
    Josh G about 9 years
    Then it will use the default equality comparer. For reference types without an equality override this is an instance comparison (are the two objects references to the same instance). For primitives the default equality will be a value comparison not an instance comparison. (var x = 4; var y = 4; x == y // is true)
  • Josh G
    Josh G about 9 years
    With default instance comparison: var x = new IntWrapper(4); var y = new IntWrapper(4); x != y // true
  • Josh G
    Josh G about 9 years
    But: var x = new IntWrapper(4); var y = x; x == y // true
  • toannm
    toannm about 9 years
    Ok Josh, i got it. Thanks again.