1

I have this function and I want to get distinct value in # Data #. but my problem is if there are two value with the same characters but one is Upper and one is Lower (i.e Comedy and comedy) it still have both value Comedy and comedy in my Data. So when I bind to Data...it shows both.

My function is:

public void LoadBookGenre(Book abc)
{
    var loadbook = from Book s in BookDB.Books where s.Genre == abc.Genre select s;
    BookAttribute.Clear();
    foreach (Book m in loadbook) BookAttribute.Add(m);
    List<Book> distinct = BookAttribute.GroupBy(a => a.Genre).Select(g => g.First()).ToList(); 
    Data.Clear(); 
    foreach (Book s in distinct) Data.Add(s);
}
i3arnon
  • 113,022
  • 33
  • 324
  • 344
EddieDuy
  • 61
  • 2
  • 10
  • change the string to either Uppercase or lowerCase in order to check the distinct.. – Vishal Dec 30 '13 at 10:26
  • 1
    you can check this http://stackoverflow.com/questions/283063/linq-distinct-operator-ignore-case – Bakri Dec 30 '13 at 10:28

3 Answers3

5

You can use the GroupBy overload that allows you to specify a case-insensitive comparer:

List<Book> distinct = 
    BookAttribute.GroupBy(a => a.Genre, StringComparer.OrdinalIgnoreCase)
                 .Select(g => g.First())
                 .ToList();

Depending on your scenario, you might also be able to use Distinct:

List<string> distinctGenres = 
    BookAttribute.Select(a => a.Genre)
                 .Distinct(StringComparer.OrdinalIgnoreCase)
                 .ToList();

Edit: You also need to alter the equality check in your initial query:

var loadbook = from Book s in BookDB.Books 
               where s.Genre.Equals(abc.Genre, StringComparison.OrdinalIgnoreCase)
               select s;
Douglas
  • 53,759
  • 13
  • 140
  • 188
1

The common solution is to maintain a version of the string that is forced to upper or lower case with upper() or lower(), and use that internal string for comparisons and the original string as the "display" version.

zxq9
  • 13,020
  • 1
  • 43
  • 60
  • Its not clear to me whether you are using a database backend or some other storage, or your own data store object. Most databases automatically build an index of the sort I'm talking about, you just need to query it the right way if you're using one (Postgres, MSSQL, Oracle, whatever); if its your own data storage object, create two entries for the string value: str_data = string; search_data = string.upper(); or whatever, and query over search_data, but display str_data on output. Sorry, to give a driveby answer; I just don't have time for an in-depth one at the moment. – zxq9 Dec 30 '13 at 10:29
  • i got the answer for my problem. anw, thanks so much ^^ – EddieDuy Dec 30 '13 at 10:37
1

Replace

Data.Add(s);

by

var found = Data.SingleOrDefault(x => x.Genre.ToUpperInvariant() == s.Genre.ToUpperInvariant());
if (found == null)
{
    Data.Add(s);
}

This way, you avoid adding the same name twice, while keeping the casing of the first one you find.

Roy Dictus
  • 32,551
  • 8
  • 60
  • 76