WaughWaugh
WaughWaugh

Reputation: 1032

What is the simplest way to partition a list based on a criteria?

Let's say, we have an object definition like this,

class MyObject {
    int id;
    string name;
}

and we have a list of MyObjects.

List<MyObject> objectList

Now, I need to partition this objectList into 2 sub-lists based on which objects have a non-null name field.

So, after the operation, I need to have 2 lists, objectsWithName where name field is non-null and objectsWithoutName where name field is null (this is the immediate criteria, but I'm looking more towards partitioning into 2 groups using a predicate).

What is the simplest way to achieve this? Can I do this in a single operation? Using LINQ is permitted.

Upvotes: 0

Views: 136

Answers (3)

Rui Jarimba
Rui Jarimba

Reputation: 18064

public class MyObject
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class MyObjectLists
{
    private readonly List<MyObject> _objects;

    public List<MyObject> NullNameObjects
    {
        get
        {
            return _objects.Where(x => x.Name == null).ToList();
        }
    }

    public List<MyObject> NonNullNameObjects
    {
        get
        {
            return _objects.Where(x => x.Name != null).ToList();
        }
    }

    public MyObjectLists(List<MyObject> objects)
    {
        _objects = objects ?? throw new ArgumentNullException(nameof(objects));
    }
}

Using the code:

var list = new List<MyObject>
{
    new MyObject
    {
        Id = 1,
        Name = "John"
    },

    new MyObject
    {
        Id = 2
    },

    new MyObject
    {
        Id = 3,
        Name = "Mary"
    },

    new MyObject
    {
        Id = 4
    }
};

var objects = new MyObjectLists(list);

foreach (MyObject myObject in objects.NonNullNameObjects)
{
    Console.WriteLine($"Object with Id {myObject.Id} has a non-null name");
}

foreach (MyObject myObject in objects.NullNameObjects)
{
    Console.WriteLine($"Object with Id {myObject.Id} has a null name");
}

Upvotes: 1

T&#226;n
T&#226;n

Reputation: 1

I think you're looking for something like this example:

class MyObject 
{
    int id;
    string name;
}

var objectList = new List<MyObject>();

objectList.Add(new MyObject { name = "item 1" });
objectList.Add(new MyObject { name = string.Empty });
objectList.Add(new MyObject { name = "item 3" });

var objectsWithName = objectList.Where(x => !string.IsNullOrEmpty(x.name));
var objectsWithoutName = objectList.Except(objectsWithName);

I've created 2 lists that the first list contains the MyObject items with the name property is NOT null, otherwise to the second's.

Upvotes: 0

Patrick Hofman
Patrick Hofman

Reputation: 156998

Two LINQ statements would do:

var nameNotNull = objectList.Where(o => !string.IsNullOrEmpty(o.Name));
var nameNull = objectList.Where(o => string.IsNullOrEmpty(o.Name));

Of course, you could use GroupBy, or a more efficient foreach statement.

To show the foreach option:

List<MyObject> nameNotNull = new List<MyObject>();
List<MyObject> nameNull = new List<MyObject>();

foreach (MyObject o in objectList)
{
    if (!string.IsNullOrEmpty(o.Name))
    {
        nameNotNull.Add(o);
    }
    else
    {
        nameNull.Add(o);
    }
}

Upvotes: 2

Related Questions