2011-02-23 3 views
1

나는 다음과 같은 코드가 있습니다모든 것을 제외 LINQ 쿼리의 결과를 제외

 public IList<Tweet> Match(IEnumerable<Tweet> tweetStream, IList<string> match, IList<string> exclude) 
    { 
     var tweets = from f in tweetStream 
        from m in match 
        where f.Text.ToLowerInvariant().Contains(m) 
        select f; 

     var final = from f in tweets 
        from e in exclude 
        where !f.Text.ToLowerInvariant().Contains(e.ToLowerInvariant()) 
        select f; 

     return final.Distinct().ToList<Tweet>(); 
    } 

나는 final 결과 집합을 포함하지 않은 내가 지금 행복하게 일치 된 최대 테스트를 구축했습니다를 IList<string>exclude이 비어 있으면 제외 항목이 추가되었습니다. 모든 항목이 제거됩니다.

 [TestMethod] 
    public void Should_exclude_items_from_exclude_list() 
    { 
     IEnumerable<Tweet> twitterStream = new List<Tweet> 
               { 
                new Tweet("I have a Mazda car"), 
                new Tweet("I have a ford"), 
                new Tweet("Mazda Rules"), 
                new Tweet("My Ford car is great"), 
                new Tweet("My renault is brill"), 
                new Tweet("Mazda cars are great") 
               }; 
     IList<string> matches = new List<string>{"mazda","car"}; 
     IList<string> exclude = new List<string>{"ford"}; 

     Matcher target = new Matcher(); 
     IList<Tweet> actual = target.Match(twitterStream, matches, exclude); 

     Assert.AreEqual(3, actual.Count);    
    } 

하지만이 테스트는 지금 실패 : 예상대로

그래서이 테스트에 통과

 [TestMethod] 
    public void Should_match_items_either_mazda_or_car_but_no_duplicates() 
    { 
     IEnumerable<Tweet> twitterStream = new List<Tweet> 
               { 
                new Tweet("I have a Mazda car"), 
                new Tweet("I have a ford"), 
                new Tweet("Mazda Rules"), 
                new Tweet("My Ford car is great"), 
                new Tweet("My renault is brill"), 
                new Tweet("Mazda cars are great") 
               }; 
     IList<string> matches = new List<string>{"mazda","car"}; 
     IList<string> exclude = new List<string>(); 

     Matcher target = new Matcher(); 
     IList<Tweet> actual = target.Match(twitterStream, matches, exclude); 

     Assert.AreEqual(4, actual.Count); 
    } 

내가 정말 간단 뭔가를 놓친거야 알고 있지만 시간에 대한 코드를 응시 후 그게 내게 오지 않는다. 나는이 문장의 나머지 부분은 평가되지 않습니다 올바른 생각하면 그래서 당신의 선택이 결코 발생하지, 비어에서 두 번째 이후

var final = from f in tweets 
      from e in exclude 
      where !f.Text.ToLowerInvariant().Contains(e.ToLowerInvariant()) 
      select f; 

:

답변

5

글쎄, 나는 그것이 실패 왜 알고 : 그것은이 절입니다 : 하늘의 콜렉션이 될 것, 그래서 항목이없는 것

from e in exclude 

심지어 where 절을 칠. 그래서 네트워크에서 읽거나 않는 경우에도 - 나뿐만 아니라 msarchet의 접근 방식을 고려하지만

var final = from f in tweets 
      let lower = f.Text.ToLowerInvariant() 
      where !exclude.Any(e => lower.Contains(e.ToLowerInvariant()) 
      select f; 

, 이것에 대한 좋은 것은 그것이 한 번만 tweetStream을 평가 끝나는 것입니다 :

여기에 또 다른 접근 방식 고통스럽고 걱정할 필요가 없습니다. 가능하다면 (그리고 편리하다) LINQ 스트림을 두 번 이상 평가하지 않도록 노력한다. 물론

, 당신은 매우 쉽게 모든 것을 하나의 쿼리를 만들 수 있습니다

var tweets = from f in tweetStream 
      let lower = f.Text.ToLowerInvariant() 
      where match.Any(m => lower.Contains(m.ToLowerInvariant()) 
      where !exclude.Any(e => lower.Contains(e.ToLowerInvariant()) 
      select f; 

나는 심지어 청소기, 정직 :

+0

@JonSkeet 수 있다고 생각 하는데요, 나는 실제로 당신을 이길 대답해라, 세상은 끝나고있다. : D – msarchet

+1

@msarchet : 공정하지 않습니다, 아내는 드레스 평가에 도움이 필요했습니다 :) (그리고 어쨌든, 이제는 지정된 이유 때문에.) –

+0

@JonSkeet, 네, 깨끗한 버전입니다 – msarchet

1

그래서 무슨 일이 일어나고 있는지이있다.

그래서 (이 아무것도받지 않습니다 제외 할 것이없는 그렇다면) exculde하는 트윗의 목록을 얻을 것이다이 대신

var excludeTheseTweet = from f in tweets 
         from e in exclude 
         where f.Text.ToLowerInvariant().Contains(e.ToLowerInvariant()) 
         select f; 

return tweets.Except(excludeTheseTweets).Distinct().ToList<Tweet>(); 

처럼이 일을 시도하고 다음 해당 항목이 형성 제거합니다 원래 목록.