Cristi
Cristi

Reputation: 1328

Get count of all items in a list that have one of the properties in another list

I am wondering if/how I can do the following thing using LINQ: I have a list of objects with some properties and another list of different distinct values corresponding to a certain property.

Example:

A = [{id=1, property=1}, {id=2, property=1}, {id=3, property=2}]
B = [1, 2]

Is there a way of achieving the following thing (obtaining the counts list) using only LINQ?

var counts = new List<int>();
foreach (var b in B)
{
    counts.Add(A.Where(a => a.property == b).Count();
}

Sample code:

public class MyObject
{
    public MyObject(int id, int prop)
    {
        Id = id;
        Property = prop;
    }
    public int Id { get; set; }
    public int Property { get; set; }

    public void test()
    {
        var A = new List<MyObject>
        {
            new MyObject(1, 1), new MyObject(2, 1), new MyObject(3, 2)
        };
        var B = new List<int>{1, 2};

        // LINQ magic

        // 2 objects with property 1
        // 1 object with property 2
    }
}

Upvotes: 0

Views: 5905

Answers (5)

ChiralMichael
ChiralMichael

Reputation: 1224

This is the gist of what you need. I'm typing this without a c# compiler, so hopefully this doesn't have errors.

var results = 
    from a in A
    join b in B on a.property equals b
    group a by a.property into g
    select new { Property = g.Key, Count = g.Count() }

Upvotes: 0

Rufus L
Rufus L

Reputation: 37020

Sure, you can just loop through the values and, for each one, get the count of items that have Property == value.

In the sample below, I'm selecting an anonymous type that contains the Value and the Count of each item that has Property == value:

public class Data
{
    public int Id { get; set; }
    public int Property { get; set; }
}

public class Program
{
    private static void Main()
    {
        var allData = new List<Data>
        {
            new Data {Id = 1, Property = 1},
            new Data {Id = 2, Property = 1},
            new Data {Id = 3, Property = 2},
        };

        var values = new[] {1, 2};

        var results = values.Select(value => 
            new {Value = value, Count = allData.Count(item => item.Property == value)});

        foreach (var result in results)
        {
            Console.WriteLine($"{result.Count} objects with Property {result.Value}");
        }
    }
}

Output

![![enter image description here

Upvotes: 1

John von No Man
John von No Man

Reputation: 3030

Yes, use select operators to only select the specific properties you want to compare, and then use intersect and count to get the count. Example:

var listOfObjects = new List<PocoClass>()
{
    new PocoClass(){Id=1,Property=3},
    new PocoClass(){Id=2,Property=2}
};

var intArray = new int[] { 1, 2, 3 };

var count = listOfObjects.Select(o => o.Property).Intersect(intArray).Count();

Upvotes: 2

Aleks Andreev
Aleks Andreev

Reputation: 7054

You can use Count method with a predicate:

var A = new[] {new {id = 1, property = 1}, new {id = 2, property = 1}, new {id = 3, property = 2}};
var B = new[] {1, 2};

var count = B.Count(b => A.Any(a => a.property == b));

Code above will check every member in B and if at least one member in A have a property with that value it will be counted

Upvotes: 1

Bambam Deo
Bambam Deo

Reputation: 177

convert B to List and run ForEach on it

B.OfType<int>().ToList().ForEach(m=>{ 
      counts.Add(A.Where(a => a.property == m).Count();
})

Upvotes: 0

Related Questions