根据属性获取列表中项目的索引

25

在我的 MyList List<Person> 中可能有一个 Person,它的 Name 属性设置为 "ComTruise"。我需要找到第一次出现 "ComTruise" 的索引位置,但不需要整个 Person 元素。

我现在正在做的是:

string myName = ComTruise;
int thatIndex = MyList.SkipWhile(p => p.Name != myName).Count();
如果列表非常大,有没有更优的方式来获取索引?

2
这基本上就是IndexOf的作用... - It'sNotALie.
MyList是你自己的集合还是List<Person>? - Shawn Wildermuth
抱歉,我纠正一下。IndexOf的语法应该是什么? - Sturm
你只需要第一个实例还是所有索引?IndexOf只会返回它遇到的第一个实例的索引。 - keyboardP
第一次实例看起来对我来说还不错。 - Sturm
1
嗯,既然它实际上不是 List<T>,你 可以 使用 myList.Select((person, index) => new { Person = person, Index = index }).FirstOrDefault(entry => entry.Person.Name == myName); 但说实话,我不确定这是否比你的方式更好(虽然它会给你一个 null 结果而不是 Count 如果该项不存在于列表中。如果 "不存在" 的神奇值为 thatIndex 等于 MyList.Count,则这可能比 thatIndex 更直观)。 - Chris Sinclair
4个回答

46
你可以使用 FindIndex
string myName = "ComTruise";
int myIndex = MyList.FindIndex(p => p.Name == myName);

注意:如果在列表中找不到符合所提供谓词定义的条件的项,则FindIndex会返回-1。


哎呀,实际上它是一个ObservableCollection而不是List,有没有相当的东西?我以为在这种情况下它们是一样的。 - Sturm
如果我使用.ToList()方法将我的ObservableCollection转换为List,它的效果非常好。谢谢! - Sturm
破解,这肯定会帮助你解决问题,但你也可以不进行转换来完成它(其他答案已经展示了如何做=D)。 - Chris
3
信息:如果没有找到,返回-1。 - GorvGoyl
1
寻找“ComTruise”就像是一个不可能完成的任务。 - Pic Mickael

27

由于它是一个ObservableCollection,你可以尝试这样做

int index = MyList.IndexOf(MyList.Where(p => p.Name == "ComTruise").FirstOrDefault());

如果你的集合中不存在"ComTruise",它将返回-1

正如评论中提到的,这将执行两次搜索。你可以用for循环进行优化。

int index = -1;
for(int i = 0; i < MyList.Count; i++)
{
    //case insensitive search
    if(String.Equals(MyList[i].Name, "ComTruise", StringComparison.OrdinalIgnoreCase)) 
    {
        index = i;
        break;
    } 
}

所以,你首先找到它,然后再去寻找它?这相当低效。 - svick
你说得对,如果列表很大,使用For循环会更好。我已经更新了我的答案。 - keyboardP
你为什么要更改比较方式以匹配子字符串?例如,“X-ComTruise”的名称将与您的“不区分大小写搜索”匹配。 - svick
因为今天是那些日子之一 ;) - keyboardP
2
你可以使用MyList.FirstOrDefault(...)来使代码更简单,而不是使用MyList.Where(..).FirstOrDefault())。 :) - Philipp

8

也许编写一个简单的扩展方法来实现这个功能是有意义的:

public static int FindIndex<T>(
    this IEnumerable<T> collection, Func<T, bool> predicate)
{
    int i = 0;
    foreach (var item in collection)
    {
        if (predicate(item))
            return i;
        i++;
    }
    return -1;
}

0
var p = MyList.Where(p => p.Name == myName).FirstOrDefault();
int thatIndex = -1;
if (p != null)
{
  thatIndex = MyList.IndexOf(p);
}

if (p != -1) ...

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