2012-04-27 2 views
1

내 질문은 Finding Consecutive Items in List using Linq과 비슷합니다. 단, 틈이없는 마지막 연속 항목을 얻고 싶습니다. 예를 들어 :LINQ로 마지막 x 연속 항목 가져 오기

2, 4, 7, 8 

출력

7,8 

또 다른 예 :

4,5,8,10,11,12 

출력

10,11,12 

방법이 수행 할 수 있습니다?

{10, 11, 12} 

I :

+3

두 번째 예제의 결과가 10,11,12가 아닌 이유는 무엇입니까? –

+0

최상의 답변은 컬렉션 유형에 따라 다릅니다. – Joe

+2

그리고 왜 Linq와 함께 이것을하고 싶습니까? – Cameron

답변

10

나는 순서에서 그래서 ... 당신은 하나 명 이상의 멤버의 마지막 연속 순서를 원하는에 믿고있어

{4, 5, 8, 10, 11, 12, 15} 

당신은 순서를 기다리고있어 마지막 시퀀스가 ​​단일 멤버 만 가질 수있는 경우 제거 할 줄을 표시했습니다.

{15} 
new[] {4, 5, 8, 10, 11, 12, 15} 
    .Select((n,i) => new {n, i}) 
    .GroupBy(x => x.n - x.i) //this line will group consecutive nums in the seq 
    .Where(g => g.Count() > 1) //remove this line if the seq {15} is expected 
    .Select(x => x.Select(xx => xx.n)) 
    .LastOrDefault() 

순서의 번호를 오름차순 것을 여기에 숨겨진 가정있다 :다음은 LINQ입니다. 그렇지 않은 경우 finding contiguous items in a sequence에 대한 Microsoft의 확장 방법 권한을 등록해야합니다. 이 경우 알려주십시오.

+1

숫자를 기준으로 한 +1 그룹화는 매우 매끄러운 트릭입니다. 위의 트릭에서는 영리한 대답으로는 – MerickOWA

+0

+1이지만 GroupBy의 비효율을 고려하면 큰 목록에서는이 방법을 사용하는 것을 싫어합니다. – yamen

3

이 작동하고 아마이 경우 쉽고 LINQ보다 효율적입니다 :

var list = new[] { 2, 4, 7, 8 }; 
List<int> lastConsecutive = new List<int>(); 
for (int i = list.Length - 1; i > 0; i--) 
{ 
    lastConsecutive.Add(list[i]); 
    if (list[i] - 1 != list[i - 1]) 
     break; 
    if(i==1 && list[i] - 1 == list[i - 1]) // needed since we're iterating just until 1 
     lastConsecutive.Add(list[0]); 
} 
lastConsecutive.Reverse(); 
1

나는이 말과 말의 둘 다 실현, 그러나 이것은 아마도 여전히 LINQ를 사용하여 여기에 가장 빠른 방법입니다.

시험 목록 :

var list1 = new List<int> {2,4,7,8}; 
var list2 = new List<int> {4,5,8,10,11,12,15}; 

있어서

이 하나의 전면 및 후면 검사 요소 페어 내지 간다
public List<int> LastConsecutive(List<int> list) 
{ 
    var rev = list.AsEnumerable().Reverse(); 

    var res = rev.Zip(rev.Skip(1), (l, r) => new { left = l, right = r, diff = (l - r) }) 
       .SkipWhile(x => x.diff != 1) 
       .TakeWhile(x => x.diff == 1); 

    return res.Take(1).Select(x => x.left) 
       .Concat(res.Select(x => x.right)) 
       .Reverse().ToList(); 
} 

만들이 연속되는 시작할 때의 요소를 고려합니다 (SkipWhile)까지 그들은 연속적으로 끝난다 (TakeWhile).

그런 다음 해당하는 쌍 번호를 꺼내고 (원래 목록에서 왼쪽 번호를 누른 다음 모든 올바른 번호를 빼내어) 다시 되돌립니다. 긴급한 버전과 비슷한 효율성을 가지지 만 LINQ 덕분에 읽기가 더 간단합니다.

+0

.Zip() 구문에 문제가 있습니다. 그것은 당신이 세 가지 매개 변수를 공급하려한다고 생각합니다. – 4thSpace

+0

정확히 그대로 붙여 넣기 때문에 제대로 작동합니다. 복사를 확인하십시오. 이것은 .NET 4.0입니다. – yamen

관련 문제