Microsoft Developer Network > Forums Home > Archived Forums Forums > LINQ Project General > Linq query for SortedList with inner List
Ask a questionAsk a question
 

AnswerLinq query for SortedList with inner List

  • Thursday, October 29, 2009 9:52 AMVinodonly Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    I have a sorted list defined in this way

    SortedList

     

    <COInfo, List<GlobalInfo>> COInfoList;

    CoInfo is a object which holds company info. Key col is Company Name..

    GlobalInfo is a object which is having cols like Nationality, Language Code..

    I want to run a query which can return

    Language code (i.e. En, Ar, etc..)

    Where Company Name is the passed company name
    and Nationality is a particular nationality..

    The one where clause is on the key element of sorted list and other is on the value element of sorted list..

    I tried various options like below but none of them is working..

    var

     

    Temp = from CO in COInfoList

     

    where CO.Key.Company == Company

     

    select CO.Value.Where( o => o.Nationality == FiltValue).Single().LangCode.ToString();


    IMP : There might be a delay in posting replies due to time difference (GMT +2:00) and Friday's Holiday instead of Sunday.

Answers

  • Saturday, October 31, 2009 5:12 PMAhmad Mageed Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     AnswerHas Code
    I meant that a second call to Single() is needed to get the actual string value. Here's how the query looks:

        var originalQuery = from CO in COInfoList
                where CO.Key.Company.Equals(Company, StringComparison.InvariantCultureIgnoreCase)
                select CO.Value.Where(o => o.Nationality.Equals(FiltValue, StringComparison.InvariantCultureIgnoreCase))
                                .Single().LangCode.ToString();
    

    Analyzing the last line,  the Single() call returns the GlobalInfo item that matched the whole filtration process, returning an IEnumerable<GlobalInfo> with 1 item. The LangCode call returns an IEnumerable<SupportedLanguages>. Finally, the ToString() call returns an IEnumerable<string>. In all these cases you have 1 item in an IEnumerable collection. It seems somewhat odd, but in order to access it, you can call Single() once again:

        var originalQuery = from CO in COInfoList
                where CO.Key.Company.Equals(Company, StringComparison.InvariantCultureIgnoreCase)
                select CO.Value.Where(o => o.Nationality.Equals(FiltValue, StringComparison.InvariantCultureIgnoreCase))
                                .Single().LangCode.ToString();
    	string result = originalQuery.Single();
    

    Does that address your question?

    Another way to write this query that might be less confusing is to use SelectMany to flatten the nested collections:

    string langCode = (from CO in COInfoList
           where CO.Key.Company.Equals(Company, StringComparison.InvariantCultureIgnoreCase)
           from i in CO.Value
           where i.Nationality.Equals(FiltValue, StringComparison.InvariantCultureIgnoreCase)
           select i.LangCode).Single().ToString();
    langCode.Dump();
    
    string langCode2 = COInfoList.Where(CO => CO.Key.Company.Equals(Company, StringComparison.InvariantCultureIgnoreCase))
                     .SelectMany(CO => CO.Value, (CO, i) => new { CO = CO, i = i })
                     .Where(o => o.i.Nationality.Equals(FiltValue, StringComparison.InvariantCultureIgnoreCase))
                     .Select(o => o.i.LangCode)
                     .Single().ToString();
    

    Document my code? Why do you think it's called "code"?
    • Marked As Answer byVinodonly Sunday, November 01, 2009 10:45 AM
    •  

All Replies

  • Thursday, October 29, 2009 2:36 PMAhmad Mageed Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Has Code
    By "none of them is working" you mean no results are returned? Or is an error being thrown? You might be running into a case-sensitivity issue since you're using == to compare the string values for Company and FiltValue. If the company you're searching for is "Microsoft" but you pass in a lower case "microsoft" then it will not match. Same thing for FiltValue.

    So either ensure you're passing in the correct value, with matching case, or perform a case insensitive comparison, such as:

    var query = from CO in COInfoList
                where CO.Key.Company.Equals(Company, StringComparison.InvariantCultureIgnoreCase)
                select CO.Value.Where(o => o.Nationality.Equals(FiltValue, StringComparison.InvariantCultureIgnoreCase))
                                .Single().LangCode.ToString();
    

    Document my code? Why do you think it's called "code"?
  • Thursday, October 29, 2009 4:22 PMVinodonly Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Sorry my post was incomplete, it is giving me a err.. with this query i was hoping that i will get a string as a result but instead i'm getting a collection back.. and this is the error i'm getting..

    Error 1 Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<string>' to 'string'

    i simply want a correct query which can return me langcode as a string of a passed company and passed nationality from the sorted list..

    IMP : There might be a delay in posting replies due to time difference (GMT +2:00) and Friday's Holiday instead of Sunday.
  • Thursday, October 29, 2009 5:01 PMAhmad Mageed Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    How is LangCode declared in the GlobalInfo class? Can it have multiple codes per Nationality? Can you provide a small working sample of the SortedList?
    Document my code? Why do you think it's called "code"?
  • Friday, October 30, 2009 10:34 AMVinodonly Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Langcode is enum.. this is how it is being filled..

    List

     

    <GlobalInfo> GlobalInfoList = new List<GlobalInfo>()

    {

     

    new GlobalInfo() {Nationality = "BANGLADESHI", LangCode = SupportedLanguages.Bn},

     

    new GlobalInfo() {Nationality = "JORDANIAN", LangCode = SupportedLanguages.Ar},

     

    new GlobalInfo() {Nationality = "SRILANKAN", LangCode = SupportedLanguages.Si}

    };

    this is how CoInfoList is getting filled..

    COInfoList =

    new SortedList<COInfo, List<GlobalInfo>>()

    {

    {

    new COInfo() {Company = "MYCOMP", Currency = "USD"}, GlobalInfoList}

    };


    IMP : There might be a delay in posting replies due to time difference (GMT +2:00) and Friday's Holiday instead of Sunday.
  • Saturday, October 31, 2009 1:22 AMAhmad Mageed Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Has Code
    Sorry my post was incomplete, it is giving me a err.. with this query i was hoping that i will get a string as a result but instead i'm getting a collection back.. and this is the error i'm getting..

    Error 1 Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<string>' to 'string'

    i simply want a correct query which can return me langcode as a string of a passed company and passed nationality from the sorted list..

    IMP : There might be a delay in posting replies due to time difference (GMT +2:00) and Friday's Holiday instead of Sunday.

    You are likely getting this error because the query returns an IEnumerable<string> and you're trying to assign it to a string variable. That assignment isn't shown in your code above.

    Using the same query I gave earlier, you would get that error if you wrote:
    string result = query;
    
    However, since it's a collection you need to use Single() to return the value from the sequence:

    string result = query.Single();
    

    Note that you should consider using SingleOrDefault() in the original query and the result in case your filter returns no results, otherwise an exception will be thrown.

    Document my code? Why do you think it's called "code"?
  • Saturday, October 31, 2009 8:24 AMVinodonly Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Kindly note i'm already using single but result is same. it is the same query which i have given before except you can change var to string, it is not working, this is what is my question that why this is not returning a single element when i'm giving it already..

    string Temp = from CO in COInfoList

     

     

    where CO.Key.Company == Company

     

     

    select CO.Value.Where( o => o.Nationality == FiltValue).Single().LangCode.ToString();

     


    IMP : There might be a delay


    IMP : There might be a delay in posting replies due to time difference (GMT +2:00) and Friday's Holiday instead of Sunday.
  • Saturday, October 31, 2009 5:12 PMAhmad Mageed Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     AnswerHas Code
    I meant that a second call to Single() is needed to get the actual string value. Here's how the query looks:

        var originalQuery = from CO in COInfoList
                where CO.Key.Company.Equals(Company, StringComparison.InvariantCultureIgnoreCase)
                select CO.Value.Where(o => o.Nationality.Equals(FiltValue, StringComparison.InvariantCultureIgnoreCase))
                                .Single().LangCode.ToString();
    

    Analyzing the last line,  the Single() call returns the GlobalInfo item that matched the whole filtration process, returning an IEnumerable<GlobalInfo> with 1 item. The LangCode call returns an IEnumerable<SupportedLanguages>. Finally, the ToString() call returns an IEnumerable<string>. In all these cases you have 1 item in an IEnumerable collection. It seems somewhat odd, but in order to access it, you can call Single() once again:

        var originalQuery = from CO in COInfoList
                where CO.Key.Company.Equals(Company, StringComparison.InvariantCultureIgnoreCase)
                select CO.Value.Where(o => o.Nationality.Equals(FiltValue, StringComparison.InvariantCultureIgnoreCase))
                                .Single().LangCode.ToString();
    	string result = originalQuery.Single();
    

    Does that address your question?

    Another way to write this query that might be less confusing is to use SelectMany to flatten the nested collections:

    string langCode = (from CO in COInfoList
           where CO.Key.Company.Equals(Company, StringComparison.InvariantCultureIgnoreCase)
           from i in CO.Value
           where i.Nationality.Equals(FiltValue, StringComparison.InvariantCultureIgnoreCase)
           select i.LangCode).Single().ToString();
    langCode.Dump();
    
    string langCode2 = COInfoList.Where(CO => CO.Key.Company.Equals(Company, StringComparison.InvariantCultureIgnoreCase))
                     .SelectMany(CO => CO.Value, (CO, i) => new { CO = CO, i = i })
                     .Where(o => o.i.Nationality.Equals(FiltValue, StringComparison.InvariantCultureIgnoreCase))
                     .Select(o => o.i.LangCode)
                     .Single().ToString();
    

    Document my code? Why do you think it's called "code"?
    • Marked As Answer byVinodonly Sunday, November 01, 2009 10:45 AM
    •