views:

721

answers:

4

Hi folks,

i have an IList<Animals> farmAnimals;

this list has three types,

  • Cows
  • Sheep
  • Chickens

how can i remove all the Chickens from the list using a lambda query or linq-to-objects so i have a separate list of chickens and the original list now only has cows and sheep.

Do i have to make three lists (the original + 2 new ones, filtered) and then null the original list? or is there a trickier way?

result needs to be

IList<Aniamls> chickens;
IList<Animals> farmAnimals; // only contains the cows and sheep, now.

cheers!

CLARIFICATION QUESTION:

what is more performant? FindAll & RemoveAll versus the Where suggestion?

+2  A: 
var chickens = farmAnimals.ToList().FindAll (c => c.Type == "Chicken");
farmAnimals.RemoveAll(a => a.Type=="Chicken");
Barbaros Alp
or c => c is Chickens
Ray
Doesn't RemoveAll returns an int? is that the number of items LEFT or REMOVED? i also prefer 'is' over .Type == 'blah'.
Pure.Krome
Actually RemoveAll does not return a collection, it returns the number of items removed.
Tim Jarvis
hmm,c is your Animal classc.Type is Animal.Typeis this what did you ask ?
Barbaros Alp
nope. c => c is Chicken is correct, becuase Chicken : Animal (chicken inherits animal).
Pure.Krome
sorry about RemoveAll, my fault
Barbaros Alp
This will process the original sequence 3 times, once for each ToList() and once for the RemoveAll(). Linq is not the best solution; since you needs 2 lists in the end, you should use an imperative approach.
Bryan Watts
is there any performance loss while doing farmAnimals.ToList()i mean is it casting IList to List ? doing some kind of casting inside a loop ?
Barbaros Alp
The performance loss is that you are processing the original sequence multiple times: the first ToList(), the FindAll(), the second ToList(), and the RemoveAll(). See my answer for an imperative approach which processes "farmAnimals" only once.
Bryan Watts
I understand,thank you very much Bryan
Barbaros Alp
+1  A: 
var chickens = farmAnimals.Where(a => a.GetType() == typeof(Chicken)).ToList();
farmAnimals = farmAnimals.Where(a => a.GetType() != typeof(Chicken)).ToList();
Brett
interesting use of Where. maybe replace the typeof checks with an 'is' check.
Pure.Krome
i like it, great
Barbaros Alp
A: 

var Chickens = farmAnimals.FindAll(a=>a is Chicken);

I have a terrible tendency to sway to the simplest solution possible. In this case, using the lambda only requires the .NET framework 2.0. The LINQ extension methods require 3.5.

Robert Venables
I think you need C# 3.0 for Lambdas, not 2.0.
silverCORE
Correct, Language Specification 3.0 - but it will compile and run on Framework 2.0 and does not require Framework 3 or 3.5.
Robert Venables
+2  A: 

Assuming:

public abstract class Animal {}

public class Chicken : Animal {}

you can do:

var chickens = animals.OfType<Chicken>().Cast<Animal>().ToList();

var nonChickens = animals.Except(chickens).ToList();

Edit

Any reasonable answer should be O(n), meaning each item in the original list is only processed once. Therefore, I would suggest an imperative approach:

var chickens = new List<Animal>();
var nonChickens = new List<Animal>();

foreach(var animal in animals)
{
    var list = animal is Chicken ? chickens : nonChickens;

    list.Add(animal);
}
Bryan Watts
now THAT's kewl!
Pure.Krome
are there any performance differences between Except vs RemoveAll and OfType+Cast vs FindAll ?
Pure.Krome