user2336660
user2336660

Reputation:

LINQ Query to count only certain values

I have a list that contains strings and integers that have been converted to strings. I'm trying to write a LINQ query where the count of all distinct strings that arent an integer, e.g. "Hello", "Hi, "Greetings" etc and a count of all integers but that arent strings e.g.

List x = { "1", "6", "3", "Hi", "5", "Hello", "Hi" }

Output to be:

integer count = 4
              Hi = 2
              Hello = 1

I currently have the query grouping all that arent integers correctly however each integer is being listed distinctinvely e.g.

Hi count = 2 Hello count = 1 1 count = 1 6 count = 1 3 count = 1 5 count = 1

Here is my query so far :-(

var q = from x in output
                    group x by x into g
                    let count = g.Count()
                    orderby count descending
                    select new { Value = g.Key, Count = count };

I tried to have another loop count all values that arent Hi Hello etc.

 var integerCount = q.Select(
                x => x.Value != "Hi" 
                || x.Value != "Hello")
                .Count();

But that count seems to be incorrect. Is there anyway i Could do just the 1 query that returns what I want?

Thank you.

Upvotes: 2

Views: 1341

Answers (4)

user2336660
user2336660

Reputation:

I've managed to refine some of the code above to get the result. But thank you all for your help.

var count = list.Aggregate(new { Integer = 0, Hi = 0, Hello = 0, (c, s) =>
                {
                    int c1 = c.Integer, 
                        c2 = c.Hi, 
                        c3 = c.Hello,  
                        n;
                    if (int.TryParse(s, out n)) 
                        c1++;
                    else if (s == "Hi") 
                        c2++;
                    else if (s == "Hello") 
                        c3++;
                    return new { 
                        Integer = c1, 
                        Hi = c2, 
                        Hello = c3, 
                                    };
                });

Upvotes: 0

Orel Eraki
Orel Eraki

Reputation: 12196

Steps:

  1. We should create a working collection of List<string>.
  2. For simplicity we will devide the main list into 2 lists; integers and strings; by using the int.TryParse integers parse method to decide of the value is in type Integer or not.
  3. We will take a list, and we will create groups by elements the have the same element. elem => elem.
  4. We will now create a dictionary of Key: ElementValue, and Value: Count from each group and the .Count on that group.

Code v1:

var list = new List<string> { "1", "6", "3", "Hi", "5", "Hello", "Hi" };

int num;
var integers = list.Where(elem => int.TryParse(elem, out num));
var strings = list.Where(elem => !int.TryParse(elem, out num));

var dictIntegers = integers.GroupBy(elem => elem).ToDictionary(elem => elem.Key, elem => elem.Count());
var dictStrings = strings.GroupBy(elem => elem).ToDictionary(elem => elem.Key, elem => elem.Count());

Code v2:

var list = new List<string> { "1", "6", "3", "Hi", "5", "Hello", "Hi" };

int num;
var listGroupedByElement = list.GroupBy(elem => elem).ToDictionary(elem => elem.Key, elem => elem.Count());
var dictIntegers = listGroupedByElement.Where(elem => int.TryParse(elem.Key, out num));
var dictStrings = listGroupedByElement.Where(elem => !int.TryParse(elem.Key, out num));

Upvotes: 0

Ivan Stoev
Ivan Stoev

Reputation: 205889

Here you go:

var counts = list.Aggregate(new { Integer = 0, Other = 0 }, (c, s) =>
{
    int c1 = c.Integer, c2 = c.Other, n;
    if (int.TryParse(s, out n)) c1++; else c2++;
    return new { Integer = c1, Other = c2 };
});
Debug.Print("Integers:{0} Other:{1}", counts.Integer, counts.Other);

Upvotes: 1

nlips
nlips

Reputation: 1288

List<string> items = { "1", "6", "3", "Hi", "5", "Hello", "Hi" };
var result = items.Select(x => new {
    IsInt = Int32.TryParse(x),
    TextValue = x
});
var integerCount = result.Where(x => x.IsInt).Count();
var countPerText = result.Where(x => !x.IsInt)
    .GroupeBy(x => x.TextValue)
    .Select(group => new {
        Text = group.Key,
        Count = group.Count()
    });

Upvotes: 0

Related Questions