在通用列表中获取对象的索引

14

我有一个带有两个属性(IDa和IDb)作为标识符的自定义对象列表。

每次我删除一个对象时,我需要知道它的索引。如何在不循环整个列表的情况下获取对象的索引?

List<CustomObject> list = new List<CustomObject>();
list.RemoveAll((MiniMapRecord p) => p.IDa == IDa.SystemID & p.IDb == pInputRecordMap.IDb);

1
什么类型的列表?这样的问题通常只需要2或3行代码。可以节省很多猜测。 - H H
你的列表中只包含MiniMapRecord对象,还是混合了CustomObject类? - MattDavey
可能是获取数组中特定项的索引的重复问题。 - Fragment
4个回答

20

你需要的方法是 FindIndex(Predicate)

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

它的复杂度是多少? - user437631
如果您只拥有对象的属性,那么这就是一个可行的方法。 - Josh G
1
值得一提的是,FindIndex内部使用for循环实现。 - MattDavey

8
正如其他人所述,除非你执行以下操作之一,否则没有办法避免循环查找项:
1. 记住索引。在创建列表时,将相关索引保存到成员变量中。这可能不适用于您的问题。
2. 保持列表排序并对该项进行二进制搜索。这也可能行不通,因为您有两个标识符。
使用IndexOf()是一个简单的解决方案,但它会耗费O(N)(线性时间)。

IndexOf() 如何比较两个不同的对象? - toannm
IndexOf() 使用默认的 EqualityComparer,因此如果您为项目重载了相等性,您可以控制它。否则,您可以使用 First()Single()(来自 LINQ),并传递一个谓词来测试/比较对象。var match = items.Single(item => item.Id == myId); - Josh G
谢谢Josh G,但是如果我没有为我的对象重载相等性运算符会发生什么? - toannm
然后它将使用默认的相等比较器。对于没有相等性重载的引用类型,这是一个实例比较(两个对象是否引用同一实例)。对于基元类型,默认的相等性将是值比较而不是实例比较。(var x = 4; var y = 4; x == y // is true - Josh G
使用默认实例比较: var x = new IntWrapper(4); var y = new IntWrapper(4); x != y // true - Josh G
显示剩余2条评论

6

您可以使用 IndexOf() 方法来获取您的 List<> 中给定元素的索引。

然而,需要注意的是,由于链表没有随机访问,因此除了从开头开始逐个检查一个元素之外,确实没有其他方法来查找特定元素(以及其索引)。


有没有不需要遍历整个列表的方法?我没有对象,只有它的属性。这是一个获取数千条记录并针对每条记录在列表中查找并删除的过程。 - user437631
在这种情况下,我相信MattDavey已经回答了你的问题。 - dandan78

4
使用列表的 .IndexOf() 方法查找索引,然后使用 .RemoveAt() 方法将其删除。

1
当然,如果您有要执行IndexOf的对象,您可以直接使用Remove(obj)。 - Adam Houldsworth
不完全正确。它是具有相同属性的新实例。如果我没记错,IndexOf() 是按引用传递的。 - user437631
OP没有提到通过这两个属性定位对象的任何信息。我假设对象是已知的。 - jonsca
1
在这里进行负投票似乎有点过了。从问题中并不清楚只有属性是已知的。 - Josh G

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接