단일 단계로 목록의 항목 색인을 얻는 방법은 무엇입니까?


193

반복하지 않고 목록에서 항목의 색인을 찾으려면 어떻게해야합니까?

현재 이것은별로 좋지 않습니다. 색인을 얻기 위해 동일한 항목의 목록을 두 번 검색하면됩니다.

var oProp = something;

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

답변:


435

List.FindIndex 메서드어떻습니까 ?

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

이 방법은 선형 검색을 수행합니다. 따라서이 방법은 O (n) 연산이며 여기서 n은 Count입니다.

항목을 찾지 못하면 -1을 반환합니다.


2
어때요 int index?
Dylan Czenski

2
@DylanChensky 그는 JS를 너무 많이 코딩했습니다
lennyy

9
참고로 품목을 찾을 수없는 경우 그것은 -1을 반환합니다
Daniel Filipe


71

편집 : 당신이하는 경우 에만 사용 a List<>당신은 단지 인덱스가 필요하고 List.FindIndex실제로 가장 좋은 방법입니다. 나는 다른 것을 필요로하는 사람들을 위해이 대답을 남겨 둘 것입니다 (예 :) IEnumerable<>.

Select술어에서 인덱스를 사용하는 오버로드를 사용 하므로 목록을 (인덱스, 값) 쌍으로 변환하십시오.

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있지만 원래 항목을 반환하는 대신 조건 자와 일치하는 항목의 인덱스를 반환했습니다.


그가 원하는 것은 색인 만있는 것 같습니다. List <>. FindIndex (Predicate <>)가 최선의 방법입니다. 질문 제목이 다른 방식으로 해결되지는 않지만 OP의 설명은 "int theThingIActuallyAmInterestedIn"인덱스 만 필요하다는 것이 명백합니다.
Louis Ricci

1
@ LastCoder : Aha-FindIndex를 놓쳤습니다. 예, 전적으로 동의합니다.
Jon Skeet

명확하게 말하면, 수동으로 두 번 반복하는 것보다 "인덱스 / 값-> 단일"접근 방식이 "더 나은"(여기서는 Big-O 측면에서 더 빠름)입니까? 아니면 LINQ2Objects 공급자가 반복 중 하나를 최적화 할만큼 똑똑합니까? (저는 Select와 Single이 일반적으로 O (n) 연산이라고 가정합니다)
sara

1
@kai : 기본적으로 LINQ 작동 방식을 읽어야한다고 생각합니다. 주석에서 자세히 설명하기에는 너무 복잡합니다. 그러나 ... 이것은 소스 컬렉션을 한 번만 반복합니다. LINQ는 파이프 라인을 설정하여 입력 시퀀스를 다른 시퀀스로 지연 변환 한 다음 Single()해당 시퀀스를 반복 하여 작업을 수행하고 조건 자와 일치하는 단일 항목을 찾습니다. 자세한 내용은 내 edulinq 블로그 시리즈를 참조하십시오 : codeblog.jonskeet.uk/category/edulinq
Jon Skeet

1
+1이 솔루션이 필요했습니다. 보스는 내가 한 번 똑똑하다고 생각했습니다. 익명 유형을 사용하고 해당 지역의 다음 코더에게는 명확하지 않을 수 있으므로 신중하게 문서화하는 것이 좋습니다.
Adam Wells

14

LINQ를 사용하지 않으려면 다음을 수행하십시오.

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

이렇게하면 목록을 한 번만 반복합니다.


22
@KingKing은 아무도 없다고 말했습니다.
Tomer W

1
이것이 Linq와 동일한 구현 FindIndex입니까?
Coops

2
아마도 같은 코드가 아닐 수도 있습니다. List는 몇 가지 깔끔한 최적화 기능을 제공합니다. 그러나 O (n) 미만의 정렬되지 않은 목록을 검색 할 수 있다고 믿기가 어렵 기 때문에 실제로는 실제로 비슷하다고 말할 수 있습니다.
sara

6
  1. List에서 문자열 값에 대한 인덱스를 찾는 간단한 솔루션입니다.

다음은 List Of String의 코드입니다.

int indexOfValue = myList.FindIndex(a => a.Contains("insert value from list"));
  1. List에서 정수 값에 대한 인덱스를 찾는 간단한 솔루션입니다.

정수 목록 코드는 다음과 같습니다.

    int indexOfNumber = myList.IndexOf(/*insert number from list*/);

2

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;
    }
}

즐겨.


2

누구든지 Array버전이 궁금하다면 다음과 같이 진행됩니다.

int i = Array.FindIndex(yourArray, x => x == itemYouWant);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.