252

如何在不遍历列表的情况下找到列表中项目的索引?

目前这看起来不太好 - 在列表中搜索相同的项目两次,只是为了获取索引:

var oProp = something;

int theThingIActuallyAmInterestedIn = myList.IndexOf(myList.Single(i => i.Prop == oProp));
4

8 回答 8

511

List.FindIndex 方法怎么样:

int index = myList.FindIndex(a => a.Prop == oProp);

该方法执行线性搜索;因此,此方法是 O(n) 操作,其中 n 是 Count。

如果没有找到该项目,它将返回 -1

于 2013-08-01T13:47:52.157 回答
122

对于简单类型,您可以使用“IndexOf”:

List<string> arr = new List<string>();
arr.Add("aaa");
arr.Add("bbb");
arr.Add("ccc");
int i = arr.IndexOf("bbb"); // Returns 1.
于 2014-10-29T22:32:41.143 回答
83

编辑:如果您使用 aList<>并且需要索引,那么List.FindIndex确实是最好的方法。我会把这个答案留给那些需要任何不同的人(例如在 any 之上IEnumerable<>)。

使用在谓词中采用索引的重载Select,因此您将列表转换为 (index, value) 对:

var pair = myList.Select((Value, Index) => new { Value, Index })
                 .Single(p => p.Value.Prop == oProp);

然后:

Console.WriteLine("Index:{0}; Value: {1}", pair.Index, pair.Value);

或者,如果您想要索引并且在多个地方使用它,您可以轻松编写自己的扩展方法,例如Where,但不是返回原始项目,而是返回与谓词匹配的那些项目的索引。

于 2013-08-01T13:42:28.517 回答
15

如果您不想使用 LINQ,则:

int index;
for (int i = 0; i < myList.Count; i++)
{
    if (myList[i].Prop == oProp)
    {
       index = i;
       break;
    }
}

这样你只迭代列表一次。

于 2013-08-01T13:42:48.800 回答
9
  1. 查找列表中任何字符串值的索引的简单解决方案。

    这是字符串列表的代码:

     int indexOfValue = myList.FindIndex(a => a.Contains("insert value from list"));
    
  2. 查找列表中任何数值的索引的简单解决方案。

    这是整数列表的代码:

     int indexOfNumber = myList.IndexOf(/* insert number from list */);
    
于 2017-05-17T13:48:00.920 回答
5

如果有人想知道这个Array版本,它是这样的:

int i = Array.FindIndex(yourArray, x => x == itemYouWant);
于 2019-10-08T11:56:43.093 回答
3

这是 IEnumerable 的可复制/可粘贴扩展方法

public static class EnumerableExtensions
{
    /// <summary>
    /// Searches for an element that matches the conditions defined by the specified predicate,
    /// and returns the zero-based index of the first occurrence within the entire <see cref="IEnumerable{T}"/>.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="list">The list.</param>
    /// <param name="predicate">The predicate.</param>
    /// <returns>
    /// The zero-based index of the first occurrence of an element that matches the conditions defined by <paramref name="predicate"/>, if found; otherwise it'll throw.
    /// </returns>
    public static int FindIndex<T>(this IEnumerable<T> list, Func<T, bool> predicate)
    {
        var idx = list.Select((value, index) => new {value, index}).Where(x => predicate(x.value)).Select(x => x.index).First();
        return idx;
    }
}

享受。

于 2017-11-22T11:16:11.660 回答
0

这一切都很好——但是如果你想选择一个现有的元素作为默认元素呢?在我的问题中,没有“--select a value--”选项。

这是我的代码——如果你不想检查没有结果,我想你可以把它变成一个衬里......

private void LoadCombo(ComboBox cb, string itemType, string defVal = "")
{
    cb.DisplayMember = "Name";
    cb.ValueMember = "ItemCode";
    cb.DataSource = db.Items.Where(q => q.ItemTypeId == itemType).ToList();

    if (!string.IsNullOrEmpty(defVal))
    {
        var i = ((List<GCC_Pricing.Models.Item>)cb.DataSource).FindIndex(q => q.ItemCode == defVal);
        if (i>=0) cb.SelectedIndex = i;
    }
}
于 2020-10-22T02:30:45.757 回答