简体   繁体   中英

Making a list distinct in c# of a distinct list

I am making a list distinct which is working. but the issue i have changed all the sting into lower cases values as well. But because i am trying to count the number of occurrence of the distinct value in the original list, to do this i am using nested for loops and counting the value, the problem i am facing is that in some of the stings there is a space at the end. so when comparing the two string they wouldn't match because of the space at the then which would lead the distinct List to have the same two values. is there any way around this

var distinctList = list.Distinct();

You need to Trim() first before do Distinct()

var list = new[] {" string", "string "};
var distinctList = list.Select(s => s.Trim()).Distinct();

If you also need to ignore case-sensitive:

var list = new[] {" String", "string "};
var distinctList = list.Select(s => s.Trim())
                       .Distinct(StringComparer.InvariantCultureIgnoreCase);

If your list contains null , presumably you ignore it, you can easily filter first:

var list = new[] {" String", "string ", null};

var distinctList = list.Where(s => !string.IsNullOrEmpty(s))
                       .Select(s => s.Trim())
                       .Distinct(StringComparer.InvariantCultureIgnoreCase);

In case you need to keep null on the result, create an extension method to customize Trim() :

    public static string CusTrim(this string @this)
    {
        return @this == null ? null : @this.Trim();
    }

Then you can call:

var distinctList = list.Select(s => s.CusTrim())
                       .Distinct(StringComparer.InvariantCultureIgnoreCase);

There's a better way. First, as Cuong correctly showed, you should be trimming your values to remove leading or trailing spaces.

Second, if you want the number of occurrences of each distinct value, you can group them and count them in the same Linq statement. It might look something like this (EDIT: you mentioned you had some null values you wanted to keep, which you must take into account when you call methods on your list elements):

var groupedCounts = list.Select(s=>s == null ? s : s.ToLowerInvariant().Trim())
                    .GroupBy(x=>x)
                    .Select(g=>new {g.Key, g.Count()});

The group creates a "Lookup", basically a read-only, keyed collection of IEnumerables where the key is based on the grouping projection (here we just want to compare the string, but you could conceivably also group by the first character or by other means). Then, the last Select creates an "anonymous type" with two fields, Key and Count (they're auto-named based on the values they get).

Note that the use of anonymous types is restricted to local scope; you can't return this collection in a strongly-typed manner because by definition it's not a "strong type". If this list needs to go somewhere else, such as being set to an instance property or returned from your current method, you could create Tuples instead of anonymous class instances, or KeyValuePairs, etc.

you can filter using linq.

var destinctList = list.Where(x => !String.IsNullOrWhiteSpace(x)).Select(x => x.TrimEnd()).Distinct().ToList();

This will also remove empty strings

你可以做点什么......

list.Select(i => i.Trim()).Distinct();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM