Question

Say I have two list List<NewTile> and List<OldTile>. The List<OldTile> always contains more items than the 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; }    
}

The Navigation property always contains the Scheme string for example.That's how items are related between those two lists.

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

I want to get all items from List<NewTile> where their Navigation property does not match any of them Scheme string from List<OldTile>. How do I do this using LINQ?

Was it helpful?

Solution 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.

Computational complexity of this is O(n2) I believe, so careful with handling large lists.

EDIT:

As for parsing the parameters (without HttpUtility), this can be done with an Uri and a Regex.

The trick is that since you only have a relative Uri, you need to create an absolute one on the spot.

The following method worked for me:

    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;        
    }

OTHER TIPS

You can use Where + Any and HttpUtility.ParseQueryString to check whether or not the query-string is linked with the Scheme:

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

You need to add using System.Linq and using System.Web.

Since you're using windows phone you don't have HttpUtility.ParseQueryString. So could try this approach: http://dotnetautor.de/blog/2012/06/25/WindowsPhoneParseQueryString.aspx

Apart from that you can also use string methods or regex. For example:

 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;
   }));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top