2008-10-25 5 views
1

NavigationTitle, NavigationUrl 및 IsCurrent 속성이있는 경량 클래스 인 Breadcrumb 유형의 IList가 있습니다. 그것은 웹 서버에 캐시됩니다. 나는 아래의 코드를 사용하여 IsCurrent가 true로 설정된 첫 번째 빵 부스러기까지 현재 빵 부스러기 흔적을 만드는 방법을 사용합니다. 그것의 아주 못생긴과 확실히 빠른 진흙 투성이의 의지 솔루션,하지만 난 궁금해서, 쉽게 LINQ로 refactored 수 있습니까?멋진 LINQ로 리팩토링 할 수 있습니까?

IList<Breadcrumb> crumbs = new List<Breadcrumb>(); 
bool foundCurrent = false; 
for (int a = 0; a < cachedCrumbs.Count; a++) 
{ 
    crumbs.Add(crumbs[a]); 
    if (foundCurrent) 
    { 
     break; 
    } 
    foundCurrent = (crumbs[a + 1] != null && ((Breadcrumb)crumbs[a + 1]).IsCurrent); 
} 

답변

5

: 그렇다면, 코드를 줄일 수있다.

  • 귀하의 소스는
  • 당신은이 대해 IsCurrent 설정을 가지고 처음 빵 부스러기를 추가 할 cachedCrumbs하지만, 아무것도 이후
  • TakeWhile 길을 가야하는 것 같은 소리하지 않지만, "이전 값이 있었다 점점 대해 IsCurrent는 "고통의 약간 우리는 효과적으로 마지막 값이 대해 IsCurrent 우리는 어느 정도 할 수 없다
  • 설정했다 여부를 결정하는 변수 유지하는 클로저를 사용할 수 있습니다
  • "무 조작 "는 TakeWhile가 분리 유지하는 선택을 밖으로 일하는 그래서

계속할지 여부를, 우리와 끝까지 :이 시도하지 않은

bool foundCurrent = false; 

var crumbs = cachedCrumbs.TakeWhile(crumb => !foundCurrent) 
         .Select(crumb => { 
           foundCurrent = crumb == null || !crumb.IsCurrent; 
           return crumb; }); 

,하지만 ...하지만 간단한 방법이있을 수 있습니다 작동해야 생각 .

편집 : 실제로는 직선 루프 인 은이 경우에는입니다. 그렇게 말하면, TakeWhile처럼 동작하는 또 다른 확장 메소드를 작성할 수 있습니다. 단, 을 제외하고은 조건 실패의 원인이되는 요소를 리턴했습니다.

var crumbs = cachedCrumbs.NewMethod(crumb => crumb == null || !crumb.IsCurrent); 

(나는 따라서 순간에 방법에 대한 적당한 이름의 NewMethod을 생각할 수 없다!)

+0

안녕 존,이 일했습니다! 고맙습니다. 나는 선택이 무엇을하는지 이해하지만, 나는 조금 잃어버린 .TakeWhile (빵 부스러기 => foundCurrent) - 정확하게 그 일을 무엇입니까? 그리고 select에서 selectedCurrent가 다시 나타나는 이유는 무엇입니까? – EvilSyn

+0

TakeWhile은 실제로 잘못되었습니다 - "foundCurrent"보다는 "! foundCurrent"여야합니다 - 해결했습니다. TakeWhile 람다는 단지 "우리가 현재를 찾지 못한 채 계속"입니다. 선택 람다는 기본적으로 TakeWhile 뒤에 * foundCurrent *를 설정합니다. –

1

우선이 코드는 작동하지 않습니다. 당신이 "빵 부스러기"를 사용했던 곳 중 일부는 "캐시 된 빵 부스러기"를 의미한다고 생각합니다. 내가 생각하는대로 생각의 기차뿐만 아니라 그냥 대답을 보여줍니다 그래서,이 타이핑

IList<Breadcrumb> crumbs = new List<Breadcrumb>(); 
for (int a = 0; a < cachedCrumbs.Count; a++) 
{ 
    crumbs.Add(cachedCrumbs[a]); 
    if (cachedCrumbs[a] != null && cachedCrumbs[a].IsCurrent) 
    { 
      break; 
    } 
} 
+0

안녕하세요 James. 코드가 작동하지만 방금 수준 높은 개요를 제공하려고했습니다. 내가 캐시 된 부스러기를 의미하지는 않았다. 부스러기. cachedCrumbs는 가능한 모든 빵 부스러기입니다. 실제 웹 사이트 이동 경로가 아니라 워크 플로의 단계처럼 생각하십시오. Thox는 foundCurrent를 제거하는 팁을 제공합니다! – EvilSyn

+0

아니요, James의 코멘트를 잘못 읽었습니다 - 코드에 "crumbs.Add (crumbs [a]);"가 있습니다. 어디에서 실제로 "crumbs.Add (cachedCrumbs [a]);" –

1

또 다른 대답 제임스 쿠란의 기반으로 -이 수로 : 그럼 간단 할 것 확실히 foreach 문 사용을 개선 할 ...

IList<Breadcrumb> crumbs = new List<BreadCrumb>(); 
foreach (Breadcrumb crumb in cachedCrumbs) 
{ 
    crumbs.Add(crumb); 
    if (crumb != null && crumb.IsCurrent) 
    { 
     break; 
    } 
} 
+0

foreach 루프는 부스러기가 실제로 나타나는 순서대로 액세스되는 것을 보증하지 않습니다. – chakrit

+0

숫자로 인덱싱을 지원하는 모든 유용한 컬렉션에 해당합니다. 이 관점에서 오해하는 일반적인 IList 구현을 생각해 볼 수 있습니까? –

+0

Thx for foreach .. 내가 먼저 그걸 가지고 있었지만, 어떤 이유로 그것을 꺼냈다. :) 그리고 이것은 나중에 남겨진 혼란입니다. :) – EvilSyn

1

방법에 대한을

// find the current item 
var currentItem = cachedCrumbs.First(c => c.IsCurrent); 
var currentIdx = cachedCrumbs.IndexOf(currentItem); 

// get all items upto current item 
var crumbs = cachedCrumbs.Take(currentIdx + 2); 

당신이 제공하는 술어와 일치하는 아이템까지 모든 아이템을 취하는 TakeUpto 메소드로 바꿀 수 있습니다.

var crumbs = cachedCrumbs.TakeUpto(c => c.IsCurrent); 

많은 청소기 :

public static IEnumerable<T> TakeUpto<T>(this IList<T> theList, Func<T, bool> predicate) 
{ 
    var targetItem = theList.First(predicate); 
    var targetIdx = theList.IndexOf(targetItem); 

    return theList.Take(targetIdx + 2); 
} 

그런 다음 당신이이 방법을 사용할 수에 대해 어떻게

!

nulls 및 off-by-one 사례와 IList/IEnumerable 차이점을 확인하지 않아도되지만 아이디어를 얻어야합니다. 한 번 목록을

public static IEnumerable<T> TakeUpto<T>(this IEnumerable<T> theList, Func<T, bool> predicate) 
{ 
    foreach (T element in theList) 
    { 
     yield return element; 
     if (predicate(element)) 
     { 
      break; 
     } 
    } 
} 

이 만 반복, 다양한 경우에 관련이있을 수 있습니다 :

+0

오, 좋은! 나는이 해결책을 너무 좋아한다! 고맙습니다. :) – EvilSyn

+0

Chakrit, 나는이 솔루션을 좋아하고 그것을 사용하기로 결정했습니다. 고맙습니다. :) 나는 그것의 재사용 입후보를 좋아한다. – EvilSyn

+0

Jon의 솔루션은 재사용 가능한 확장 방법으로 리팩터링 될 수 있지만 약간 복잡합니다. 가독성이 더 좋지만 다음과 같이 Jon 솔루션이 더 빨리 실행될 수 있습니다. – chakrit

1

이 답변 chakrit의 TakeUpTo의 대안 구현입니다. 업스트림 시퀀스가 ​​OrderBy 절의 결과라고 가정합니다. 이유가 없어도 여러 번 결과를 여러 번 정렬하지 않으려는 경우가 있습니다.

또한 소스로 IEnumerable<T>을 사용할 수 있습니다. 더 유연합니다.

LINQ에 대한 멋진 점 중 하나는 동일한 목표를 달성하는 여러 가지 방법입니다.

+0

감사합니다 존, 나도 정말이 솔루션을 좋아해요! – EvilSyn

관련 문제