Michael
Michael

Reputation: 13616

Remove specific items from list of objects

I have list of objects:

public class SDesc
{
    public string sensorId { get; set; }
    public string address { get; set; }
}

List<SDesc> desc = new List<SDesc>
{
    new SDesc {sensorId = "1234", address =   "Adams22"},
    new SDesc {sensorId = "5555", address =   "Hourton34"},
    new SDesc {sensorId = "4444", address =   "SaintsRoad55"},
    new SDesc {sensorId = "1258", address =   "BerryAve58"},
    new SDesc {sensorId = "52486", address =   "SaintsRoad2"},
    new SDesc {sensorId = "12361", address =   "TomassonRoad"}
}

And also I have IEnumarable of strings:

IEnumarable<string> sId = {"4444","52486","12361"};

from desc list I need to remove records where sensorsId property exists in sId list.

For example for case above the result I want to get is:

List<SDesc> desc = new List<SDesc>
{
    new SDesc {sensorId = "1234", address =   "Adams22"},
    new SDesc {sensorId = "5555", address =   "Hourton34"},
    new SDesc {sensorId = "1258", address =   "BerryAve58"},
}

Here what I tried:

desc.RemoveAll(obj => obj.sensorId == sId);

But it's not works properly because sID is IEnumarable type.

So my question is how to remove items from desc list where sensorsId property exists in sId list?

Upvotes: 1

Views: 96

Answers (2)

Yeldar Kurmangaliyev
Yeldar Kurmangaliyev

Reputation: 34189

You can use .Contains() LINQ method to check if a collection contains an item:

desc.RemoveAll(obj => sId.Contains(obj.sensorId));

However, it would lead to multiple enumeration of enumerable sId. It's not a problem in this case since this enumerable is an array in this particular case.

Read more about "possible multiple enumeration":
- Handling warning for possible multiple enumeration of IEnumerable
- Resharper's example code for explaining "Possible multiple enumeration of IEnumerable"

I would recommend converting it to a collection to make sure you enumerate IEnumerable only once.
As suggested by Evk in comments, it is better to use HashSet so that .Contains executes in O(1) time:

List<SDesc> desc = new List<SDesc> {
  new SDesc {sensorId = "1234", address =   "Adams22"},
  new SDesc {sensorId = "5555", address =   "Hourton34"},
  new SDesc {sensorId = "4444", address =   "SaintsRoad55"},
  new SDesc {sensorId = "1258", address =   "BerryAve58"},
  new SDesc {sensorId = "52486", address =   "SaintsRoad2"},
  new SDesc {sensorId = "12361", address =   "TomassonRoad"}
};

IEnumarable<string> sId = {"4444","52486","12361"};
var sIdsSet = new HashSet(sId);

desc.RemoveAll(obj => sIdsSet.Contains(obj.sensorId));

Upvotes: 2

Ehsan Sajjad
Ehsan Sajjad

Reputation: 62488

You need to use Any with it like:

 desc.RemoveAll(obj => sId.Any(x=> x== obj.sensorId ));

As method name suggests it would check if any of the item in sId matches with the item in desc against sensorId, it will remove those items from List<T>.

Upvotes: 3

Related Questions