Tìm chỉ mục của một giá trị trong một mảng


113

Có thể dùng linq bằng cách nào đó để tìm chỉ mục của một giá trị trong một mảng không?

Ví dụ, vòng lặp này định vị chỉ mục khóa trong một mảng.

for (int i = 0; i < words.Length; i++)
{
    if (words[i].IsKey)
    {
        keyIndex = i;
    }
}

Trên thực tế, chỉ cần nhận được từ là tốt.
initialZero

Câu trả lời:


183
int keyIndex = Array.FindIndex(words, w => w.IsKey);

Điều đó thực sự mang lại cho bạn chỉ mục số nguyên chứ không phải đối tượng, bất kể bạn đã tạo lớp tùy chỉnh nào


1
Tại sao điều này không được tạo thành một phương thức mở rộng System.Linqtheo mặc định? Đó là nơi mọi thứ khác như thế này là!
qJake

63

Đối với các mảng bạn có thể sử dụng Array.FindIndex<T>::

int keyIndex = Array.FindIndex(words, w => w.IsKey);

Đối với danh sách bạn có thể sử dụng List<T>.FindIndex:

int keyIndex = words.FindIndex(w => w.IsKey);

Bạn cũng có thể viết một phương thức mở rộng chung phù hợp với bất kỳ Enumerable<T>:

///<summary>Finds the index of the first item matching an expression in an enumerable.</summary>
///<param name="items">The enumerable to search.</param>
///<param name="predicate">The expression to test the items against.</param>
///<returns>The index of the first matching item, or -1 if no items match.</returns>
public static int FindIndex<T>(this IEnumerable<T> items, Func<T, bool> predicate) {
    if (items == null) throw new ArgumentNullException("items");
    if (predicate == null) throw new ArgumentNullException("predicate");

    int retVal = 0;
    foreach (var item in items) {
        if (predicate(item)) return retVal;
        retVal++;
    }
    return -1;
}

Và bạn cũng có thể sử dụng LINQ:

int keyIndex = words
    .Select((v, i) => new {Word = v, Index = i})
    .FirstOrDefault(x => x.Word.IsKey)?.Index ?? -1;

2
Ngoài ra còn có một danh sách (T) .FindIndex phương pháp
tdc

@Paolo làm thế nào về một Danh sách được tạo từ Lambda? Tôi gặp lỗi vị ngữ.
Mihir Patel

10
int keyIndex = words.TakeWhile(w => !w.IsKey).Count();

3
+1 nhưng nếu mục không tồn tại thì sao? chúng tôi sẽ nhận được 0, nhưng chỉ số là -1
Arsen Mkrtchyan

@ArsenMkrtchyan Nếu mục không tồn tại, sản lượng words.Length này
Jim Balter

@ArsenMkrtchyan Bạn đã viết "chúng ta sẽ nhận được 0" ... điều đó đã sai. Bạn đã viết "nhưng chỉ số là -1" ... điều đó cũng sai. -1 là một chỉ báo thất bại phổ biến, nhưng nó không phải là chỉ số duy nhất có thể xảy ra. Bất kỳ giá trị nào không nằm trong 0..words.Length-1 sẽ làm được.
Jim Balter,

1
@JimBalter, ý tôi là nếu mục không tồn tại thì biểu thức sẽ trả về 0, có gì sai trong đó? Tôi đồng ý rằng -1 là chỉ báo phổ biến, nhưng đồng ý rằng hiển nhiên rằng 99% trường hợp -1 là giá trị mong đợi khi mục không tồn tại. ít nhất 0 là sai khi mục không tồn tại
Arsen Mkrtchyan

7

Nếu bạn muốn tìm từ bạn có thể sử dụng

var word = words.Where(item => item.IsKey).First();

Điều này cung cấp cho bạn mục đầu tiên mà IsKey là đúng (nếu có thể không có, bạn có thể muốn sử dụng .FirstOrDefault()

Để có được cả mục và chỉ mục, bạn có thể sử dụng

KeyValuePair<WordType, int> word = words.Select((item, index) => new KeyValuePair<WordType, int>(item, index)).Where(item => item.Key.IsKey).First();

linq mất trí. Tôi đã nghĩ các generic Java thật điên rồ. Dù sao, cảm ơn vì tất cả sự giúp đỡ.
initialZero

Việc ép kiểu giá trị trả về có được chấp nhận thực tế không hay có cách nào để xác định loại từ không?
initialZero

ok, tôi nghĩ ra cái này. DecodedMessageWord keyWord = words.Where (x => x.IsKey == true) .First <DecodedMessageWord> ();
initialZero

5
@initialZero kiểm tra quá tải cho First, nó có một vị từ, bạn không cần Where.
Yuriy Faktorovich

3

Thử cái này...

var key = words.Where(x => x.IsKey == true);

2
Đây có vẻ như là một giải pháp rất yếu so với các câu trả lời của Grizzly và masenkablast. masenkablast trả lời câu hỏi ban đầu và Grizzly đưa ra giải pháp tốt hơn để tìm từ, vì "var" cuối cùng của anh ta sẽ là từ thực sự chứ không phải <TSource> IEnumerable chứa 1 từ.
James


1

Giải pháp này đã giúp tôi nhiều hơn, từ msdn microsoft :

var result =  query.AsEnumerable().Select((x, index) =>
              new { index,x.Id,x.FirstName});

querytoList()truy vấn của bạn .


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.