user3165438
user3165438

Reputation: 2661

Map List by Linq Expression

I have a generic List<Package> called packages.

I invoke for each item the method VersionControlGetStatus() from Package class. The method returns an integer value.

 List<EA.Package> list = packages.ForEach(p => p.VersionControlGetStatus());    

I would like to map the items in the list according to the returned value from the method to create several List<Package> according the returned values.

How should I update the code above?

EDIT:

For example I have 3 items in packages list: a, b, c.

When I invoke the method for each item, the returned value for a and b is 1.
The returned value for c is 8.

Desired result:

Two new List<Package>s; the first contains a and b, the second contains c.

Upvotes: 0

Views: 179

Answers (3)

Chris
Chris

Reputation: 27609

Try code based on the following:

IEnumerable<IGrouping<int, EA.Package>> groupedPackages = packages.GroupBy(p => p.VersionControlGetStatus());

foreach (IGrouping<int, EA.Package> packageGroup in groupedPackages)
{
    Console.WriteLine("Status: " + packageGroup.Key.ToString());
    Console.WriteLine("Packages:");
    foreach (EA.Package package in packageGroup)
    {
        Console.WriteLine(package.ToString());
    }
    Console.WriteLine();
}

The first line creates an IEnumerable<IGrouping<>>. The IGrouping is basically an IEnumerable that has the key used to group on it. WE can thus loop over our groupedPackages to get a packageGroup that has a key and do with that what we want. We then can loop over that packageGroup as we would any other enumerable and do what we want.

You can also do things like create a lookup from the original list to allow you to easily access a specific status with something like:

 Lookup<int, EA.Package> packageLookup = packages.ToLookup(p=>p.VersionControlGetStatus());
 IEnumerable<EA.Package> status0Packages = packageLookup[0];

Which is better for you depends on how you are going to use them.

Note: all code has been written directly into this editor window and is untested so may contain minor syntax errors or typos.

Upvotes: 1

EagleBeak
EagleBeak

Reputation: 7419

I would use GroupBy() as Typist suggested, but work with the groupings directly. They contain a list of packages and a Key:

IEnumerable<IGrouping<int,Package>> groups = packages.GroupBy(p => p.VersionControlGetStatus()).OrderBy(g => g.Key);

foreach(IGrouping<int,Package> g in groups)
{
    Console.WriteLine("Key: {0} | Count: {1}", g.Key, g.Count());

    Package first = g.First();

    Console.WriteLine("First package in group: " + first.ToString());
}

And if you want packages with a certain status:

List<Package> value1Packages = groups.Single(g => g.Key == 1).ToList();

Edit: included explicit types instead of var for clarity

Upvotes: 2

Typist
Typist

Reputation: 1474

Use Linq GroupBy clause

var listOfPackages = packages.GroupBy(p => p.VersionControlGetStatus())
                             .Select(g => g.ToList());

listOfPackages is an IEnumerable<List<package>>

This will give you 2 lists according to your example. And you can access the package from the 2 returned lists like below -

foreach(var packageList in listOfPackages) {
    foreach(var pack in packageList ) {
        // work with your pacakge
    }        
}

Upvotes: 2

Related Questions