2014-05-12 25 views
1

說我有兩個列表List<NewTile>List<OldTile>List<OldTile>總是包含比List<NewTile>更多的項目。LINQ:根據其屬性比較兩個列表,並返回匹配某些條件的項目

public class NewTile 
{ 
    public Uri Navigation { get; set; } 
    public string Info { get; set; }  
} 

public class OldTile 
{ 
    public String Scheme { get; set; } 
    public string Status { get; set; }  
} 

Navigation屬性總是包含Scheme字符串example.That的項目所使用的這兩個表之間的關係。

Scheme = "wikipedia" 
Navigation = "/Pages/BlankPage.xaml?Scheme=wikipedia" 

我想從List<NewTile>的所有項目,他們的導航屬性沒有任何人Scheme串從List<OldTile>匹配。我如何使用LINQ來做到這一點?

回答

2
IEnumerable<NewTile> filtered = newTiles // get me all new tiles... 
    .Where( 
     newTile => // ...for which it's true that... 
      oldTiles 
       .All(// ...for all the old tiles... 
        oldTile => 
         !newTile.Navigation.OriginalString.EndsWith("?Scheme=" + oldTile.Scheme))); 
         // ...this condition is met. 

這個計算複雜度是O(n2)我相信,處理大型列表時要小心。

編輯:

至於解析參數(不HttpUtility),這可以用烏里和一個正則表達式完成。

訣竅是因爲你只有一個相對的Uri,你需要在現場創建一個絕對的。

下面的方法爲我工作:

string GetScheme(string relativeUri) 
    { 
     string fakeSite = "http://fake.com"; // as the following code wouldn't work on relative Uri! 
     Uri uri = new Uri(fakeSite + relativeUri); 
     string query = uri.Query; 
     string regexPattern = Regex.Escape("?Scheme=") + "(?<scheme>\\w+)"; 
     Match match = new Regex(regexPattern).Match(query); 
     if (match.Captures.Count > 0) 
     { 
      return match.Groups["scheme"].Value; 
     } 
     return String.Empty;   
    } 
+0

很有幫助,但'Scheme'在'Navigation'中並不總是'EndWith'。在'Navigation'中可能會附加額外的字符串 – PutraKg

+0

沒關係。我只是使用'!newTile.Navigation.OriginalString.Contains' ... – PutraKg

+0

@PutraKg好吧:)我能當場想到的最好的方法就是用Uri + Regex擺弄(我更新了我的問題)。我不確定這個正則表達式是否完美(例如,可能需要關注不區分大小寫),但這是一個起點。當然,如果沒有'HttpUtility',它仍然只是一個黑客。 –

3

您可以使用Where + AnyHttpUtility.ParseQueryString檢查查詢字符串是否與Scheme鏈接:

var newNotInOld = newTiles 
    .Where(nt => !oldTiles 
     .Any(ot => ot.Scheme.Equals(HttpUtility.ParseQueryString(nt.Navigation.ToString())["Scheme"], StringComparison.InvariantCultureIgnoreCase))); 

您需要添加using System.Linqusing System.Web

由於您使用的是windows phone,因此您沒有HttpUtility.ParseQueryString。所以可以嘗試這種方法:http://dotnetautor.de/blog/2012/06/25/WindowsPhoneParseQueryString.aspx

除此之外,你還可以使用字符串方法或正則表達式。例如:

var newNotInOld = newTiles 
    .Where(nt => !oldTiles 
    .Any(ot => { 
     string url = nt.Navigation.ToString(); 
     int index = url.IndexOf('?'); 
     bool containsScheme = false; 
     if (index >= 0) 
     { 
      string queryString = url.Substring(++index); 
      containsScheme = queryString.Split('&') 
      .Any(p => p.Split('=')[0].Equals("Scheme", StringComparison.InvariantCulture) 
        && p.Split('=').Last().Equals(ot.Scheme, StringComparison.InvariantCultureIgnoreCase)); 
     } 
     return containsScheme; 
    })); 
+0

不錯,但我正在爲Windows Phone開發。 'HttpUtility.ParseQueryString'似乎不可用。 – PutraKg

+0

@PutraKg:我不知道它是否工作,但它似乎是你在找什麼:http://dotnetautor.de/blog/2012/06/25/WindowsPhoneParseQueryString.aspx除此之外,你也可以使用上述查詢中的字符串方法,例如'='上的'EndsWith'或甚至'String.Split'。 –

相關問題