2

Is there a way to remove all items except first one from any type of collection (Control.Items, List ....) using LINQ only ?

eugeneK
  • 10,750
  • 19
  • 66
  • 101

6 Answers6

4

No. LINQ is designed for querying collections (no side-effects), not for adding or removing items.

What you can do is write a query that takes the first element of the collection:

var result = source.Take(1);

Note that LINQ doesn't work with all types of collections; you need a LINQ provider to make LINQ work. For instance, source must implement IEnumerable<T> to use the extension methods of the Enumerable Class (LINQ-to-Objects).

dtb
  • 213,145
  • 36
  • 401
  • 431
2

How about something using reflection?

static void RemoveButFirst(object o){

    Type t = o.GetType();

    System.Reflection.MethodInfo rm = t.GetMethod("RemoveAt",
                                                 new Type[]{typeof(int)});
    System.Reflection.PropertyInfo count = t.GetProperty("Count");

    for (int n = (int)(count.GetValue(o,null)) ; n>1; n--)
        rm.Invoke(o, new object[]{n-1});

}   

This would work any time your collection exposed an int Count property and a RemoveAt(int) method, which I think those collections should.

And a more concise version, using dynamic, if you work with C# 4.0:

public static void RemoveBut(dynamic col, int k){
    for (int n = col.Count; n>k; n--)
        col.RemoveAt(n-1);
}
Vlad
  • 18,195
  • 4
  • 41
  • 71
  • It selects one item. I need to remove all besides 1st one – eugeneK Nov 21 '11 at 13:39
  • thanks for creative solution using reflection but i will probably stick to simple loop... – eugeneK Nov 21 '11 at 14:03
  • If only need to do it once in your code, then a simple loop will be more effective. This solution is for the frustrating case where you need to do it more than once. – Vlad Nov 21 '11 at 14:07
0

You can use .Take(1), but it returns a new collection, and leaves the original intact.

The idea of LINQ came from functional programming where everything is immutable, because of that, they didn't make it possible to modify the collections with LINQ.

Jon Skeet has a comment on the subject: LINQ equivalent of foreach for IEnumerable<T>

Community
  • 1
  • 1
Jesse van Assen
  • 2,240
  • 2
  • 16
  • 19
0

How about (in linq):

var result = list.Where(l => l != list.First());

But this would be better:

var result = list.Take(1);
Bas Slagter
  • 9,831
  • 7
  • 47
  • 78
0
        List<string> collection = new List<string>();
        collection.RemoveAll(p => p.StartsWith("something"));
shenhengbin
  • 4,236
  • 1
  • 24
  • 33
0
listXpto.Where(x=>true /* here goes your query */)
    .Select(x=>{listXpto.Remove(x); return null})

But I don´t know the real utility of that.

Remember that the remove method is for ILists, not IQueryable in general.

Hans Kesting
  • 38,117
  • 9
  • 79
  • 111
Adilson de Almeida Jr
  • 2,761
  • 21
  • 37