Gergely Kiss
Gergely Kiss

Reputation: 77

How to query a List<MyClass> with another list<int> into a new List<MyClass>

I have two lists:

static List<Parts> partList = new List<Parts>();

The class it refers to:

class Parts
{
    int chassisNumber;

    public int ChassisNumber
    {
        get { return chassisNumber; }
        set { chassisNumber = value; }
    }

    int partsCount;

    public int PartsCount
    {
        get { return partsCount; }
        set { partsCount = value; }
    }

And the another one:

static List<int> shuffledChassisList = new List<int>();

shuffledChassisList contains a subset of chassis numbers loaded into List ChassisNumber. I want to use shuffledChassisList to query the List into a new List, for ex: List filteredPartList.

I tried to use Linq but failed to write a working solution that would create a new list with filtered results.

Then, I want to use this filtered list to categorise parts into new lists depending on part number count (for ex: I want to copy all parts from List filteredPartList into List emptyPackageList where a Part's partsCount is 0).

So far I got this, but not sure what to write in the foreach loop:

static List<Parts> emptyPackageList = new List<Parts>();

var emptyPackage = filteredPartList.Where(p => p.partsCount == 0);

foreach (var part in emptyPackage)
{
    emptyPackageList.Add(new Parts(??));
}

If it is possible to write one method that does this two thing one it is fine for me.

edit: The reason why I need to have two lists is because I query a database to get the chassis numbers and the parts count which belonging to it. I asked the community, but unfortunately it seems that it is not possible to make this query to run on selected chassis numbers. So I have the partscount for all the chassisnumbers (List<Parts> partList), which I need to filter with ones I am looking for (List<int> shuffledChassisList), then group by into new lists by partscount.

If it is possible or easier to filter the List<Parts> partList by the List<int> shuffledChassisList then group by the results by partsCount and then copy the Parts into several new lists, then it is also an acceptable solution.

Upvotes: 1

Views: 94

Answers (2)

Gilad Green
Gilad Green

Reputation: 37299

Your class does not specify a constructor and thus has only the default constructor. To populate the new instance with data use the object initializer syntax:

var emptyPackage = filteredPartList.Where(p => p.partsCount == 0);
foreach (var part in emptyPackage)
{
    emptyPackageList.Add(new Parts { ChassisNumber = part.ChassisNumber, PartsCount = part.PartsCount } );
}

Also if already using linq then use .Select to project the new instances:

var emptyPackage = filteredPartList.Where(p => p.partsCount == 0)
                                   .Select(p => new Parts {
                                       ChassisNumber = part.ChassisNumber, 
                                       PartsCount = part.PartsCount 
                                   }).ToList();

Notice that this creates a deep-copy of your objects as you instantiate a new object and set its properties. If a shallow copy is enough then just:

var emptyPackage = filteredPartList.Where(p => p.partsCount == 0).ToList();

In addition consider the following:

  1. As your properties' implementations are the default ones, use auto-properties:

    class Parts
    {
        public int ChassisNumber { get; set; }
        public int PartsCount { get; set; }
    } 
    
  2. Implement a copy constructor or the IClonable interface and then:

    //copy constructor
    filteredPartList.Where(p => p.partsCount == 0).Select(p => new Parts(p));
    //clone
    filteredPartList.Where(p => p.partsCount == 0).Select(p => p.Clone());
    

If I understood your update correctly then:

var result = filteredPartList.Where(p => p.partsCount == 0 && 
                                         shuffledChassisList.Contains(p.ChassisNumber))
                             .GroupBy(p => partsCount)
                             .ToList();

Also consider changing shuffledChassisList to be a HashSet<int> so Contains will be an O(1) operation instead of O(n).

Upvotes: 2

Bruno Belmondo
Bruno Belmondo

Reputation: 2357

Maybe I did not get your proper intention but here is what you can do:

If you have a list of parts and want to categorize them by PartsCount:

var categorized = myList.GroupBy(p=>p.PartsCount, p=>p);

If you want to get all items from one list if id belonging to another:

var filtered = myList.Where(p=>idList.Contains(p.Id));

Maybe by combining both methods you can get what you want (which is still a bit unclear to me)

Upvotes: 1

Related Questions