2010-04-21 5 views
10

내 질문에 HERE을 보시고, 이제 다음 권장 사항 (해당되는 경우) 기준과 일치하는 대상을 반환하고 싶습니다.LINQ 목록의 다음 항목

그럼 내가 10 항목 중 6 항목을 찾았습니다. 쿼리 대신 항목 7을 반환하고 싶습니다.

더 좋은 방법이 있습니까? 인덱스가 있으면

int index = recommendations.FindIndex(rp => 
              rp.Products.Any(p => p.Product.Code == "A") 
             && rp.Products.Any(p => p.Product.Code == "B") 
            ); 

당신이 얻을 수 있습니다 : 당신이 List<T> 객체를 가지고 있기 때문에

답변

14

는 첫 번째 일치하는 항목의 인덱스가 아닌 항목 자체를 얻는 대신 Where의 그 FindIndex 방법을 사용할 수 있습니다 다음 항목 또는 이전 항목 또는 원하는 것을 선택하십시오.

+0

일을 SQL하는 역()이 작동하지 않습니다. –

0

항목 7이 Where 절과 일치합니까? 그렇다면, Skip()Take() 확장 방법을 사용하십시오

var myProducts = 
    from rp in recommendations 
    where 
     cp.Products.Any(p => p.Product.Code == "A") && 
     cp.Products.Any(p => p.Product.Code == "B") 
    select rp; 

var nextProduct = myProducts.Skip(1).Take(1); 
+0

나는 이것이 정확하게 작동 할 것이라고 생각하지 않는다. OPs의 경우 원본은 1 개의 결과 만 반환하고 원래 목록에서는 다음을 원할 것입니다. –

+0

@spoulson, 맞습니다. 일치하는 항목을 찾고 목록의 다음 항목을 반환하고 싶습니다. – griegs

1

을해야한다. 나는 그것을 구체적으로 테스트하지 않았다. 이 두 기록을 필요한 경우

var nextProducts = from item1 in recommendations.Select((rec, idx) => new { Rec = rec, Index = idx }) 
        join item2 in recommendations.Select((rec, idx) => new { Rec = rec, Index = idx }) 
        on item1.Index equals item2.Index - 1 
        where item1.Rec.Products.Any(p => p.Code == "A") 
        && item1.Rec.Products.Any(p => p.Code == "B") 
        select item2.Rec; 

,이 것 (select 문은

select new { MatchingItem = item1.Rec, NextItem = item2.Rec }; 

될 수있다 그러나 당신은 목록의 마지막 항목 인 일치하는 항목을 설명하는 그룹화를 수행해야 이 경우 다음 항목이 아님).

var nextProducts = from item1 in recommendations.Select((rec, idx) => new { Rec = rec, Index = idx }) 
        join item2 in recommendations.Select((rec, idx) => new { Rec = rec, Index = idx }) 
        on item1.Index equals item2.Index - 1 
        into groupjoin 
        from i2 in groupjoin.DefaultIfEmpty() 
        where item1.Rec.Products.Any(p => p.Code == "A") 
        && item1.Rec.Products.Any(p => p.Code == "B") 
        select new { MatchingItem = item1.Rec, NextItem = i2 == null ? null : i2.Rec }; 

I 테스트 문자열 목록과 유사한 것이었다했던 코드입니다.

List<string> list = new List<string>() { "a", "b", "c", "a", "d", "a", "e" }; 

var query = from item1 in list.Select((s, idx) => new { Item = s, Index = idx }) 
      join item2 in list.Select((s, idx) => new { Item = s, Index = idx }) 
      on item1.Index equals item2.Index - 1 
      where item1.Item == "a" 
      select item2.Item; 

b, d 및 e를 반환합니다. 이전 대답은 작동 Skip(1).Take(1)를 사용

MyList.SkipWhile(item => item.Name != "someName").Skip(1).FirstOrDefault() 

하지만, 하나 개의 결과 목록을 반환합니다 :

28

여기에 내 현재의 최선의 방법입니다. 내 경우 (그리고 아마도 OP의 경우), 우리는 실제 아이템을 찾고 있습니다. 그래서 우리가 찾고있는 곳으로 갈 때까지 코드가 건너 뜁니다. (Where는 부분 집합을 반환 할 것이므로 다음 항목에 액세스 할 수 없게됩니다.) 다음 하나를 건너 뛴 다음 항목을 가져옵니다.

+0

참고 :이 답변은 Microsoft 가상 아카데미 과정 'De-Mystifying LINQ'- 6 부에 언급되어 있습니다. –

4

이런 일에 대해 어떻게 :

public static class Extension 
{ 
    public static T Next<T>(this IEnumerable<T> source, Func<T, bool> predicate) 
    { 
     bool flag = false; 

     using (var enumerator = source.GetEnumerator()) 
     { 
      while (enumerator.MoveNext()) 
      { 
       if (flag) return enumerator.Current; 

       if(predicate(enumerator.Current)) 
       { 
        flag = true; 
       } 
      } 
     } 
     return default(T); 
    } 
} 

당신은 다음과 같이 호출 할 수 당신은 어디에서

Products.Next(x => x.Whatever); 
3

이 하나


다음 항목을 시도 할

MyList.SkipWhile(x => x != value).Skip(1).FirstOrDefault(); 

이전 항목 참고 : LINQ는 람다 구문의 사용을 위해

var MyList2 = MyList.ToList(); 
MyList2.Reverse(); 
MyList2.SkipWhile(x => x != value).Skip(1).FirstOrDefault(); 
+0

SQL Server에는'Reverse'가 구현되어 있지 않습니다. –

+0

http://msdn.microsoft.com/en-us/library/bb358497(v=vs.110).aspx 그것은 LINQ이고 Reverse가 여기에 있습니다 –

+0

예, LINQ API입니다. LINQ to SQL (Server) SQL에 동등성이 없기 때문에 오류가 발생합니다. –