【问题标题】:LINQ: Compare two list based on their properties and return items that match certain conditionsLINQ:根据属性比较两个列表并返回符合特定条件的项目
【发布时间】:2014-05-12 19:12:43
【问题描述】:

假设我有两个列表 List<NewTile>List<OldTile>List<OldTile> 总是比List<NewTile> 包含更多的项目。

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 字符串。这就是这两个列表之间项目的关联方式。

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

我想从List<NewTile> 获取所有项目,其中它们的导航属性与来自List<OldTile> 的任何Scheme 字符串不匹配。如何使用 LINQ 执行此操作?

【问题讨论】:

    标签: c# linq list windows-phone-8


    【解决方案1】:

    您可以使用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;
       }));
    

    【讨论】:

    • 不错,但我正在为 Windows Phone 开发。 HttpUtility.ParseQueryString 似乎不可用。
    • @PutraKg:我不知道它是否有效,但它似乎是您正在寻找的:dotnetautor.de/blog/2012/06/25/… 除此之外,您还可以在上述查询中使用字符串方法,例如 @ 987654333@ 甚至String.Split =
    【解决方案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),可以通过UriRegex来完成。

    诀窍在于,既然你只有一个相对的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;        
        }
    

    【讨论】:

    • 有帮助但Scheme 并不总是EndWithNavigation 中。 Navigation 中可能附加了额外的字符串
    • @PutraKg 好吧 :) 我能想到的最好的办法就是摆弄 Uri + Regex(我更新了我的问题)。我不确定正则表达式是否完美(例如,可能应该注意不区分大小写),但这是一个起点。当然,如果没有HttpUtility,它仍然只是一个 hack。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-11
    相关资源
    最近更新 更多