Linq Query to IEnumerable<T> Extension Method
Solution 1
That one's easy:
var query = items.Select(i => i.ID);
A select
clause always corresponds to a call to Select
. Some of the other operators end up with a rather more complex expansion :) If you work hard, you can get the compiler to do some very odd stuff...
You can find all the details of this and other query expression translations in section 7.16 of the C# specification (v3 or v4).
<plug>
You could also buy C# in Depth, 2nd edition and read chapter 11 if you really wanted to :)</plug>
Solution 2
You can use this:
var query = items.Select(i => i.ID);
A couple of other points:
Here you don't need the call to ToArray
:
foreach (string s in query.ToArray())
Also if your list is large and you are removing a lot of items you may want to use List.RemoveAll
instead of iterating. Every time you remove an item from a list all the other items after it have to be moved to fill the gap. If you use RemoveAll
this only has to be done once at the end, instead of once for every removed item.
List<Item> itemsToRemove = (List<Item>)ViewState["ItemsToRemove"];
HashSet<string> itemIds = new HashSet<string>(itemsToRemove.Select(s => s.ID));
saleItems.RemoveAll(c => itemIds.Contains(c.ID));
Solution 3
public static class ItemCollectionExtensions
{
public static IEnumerable<int> GetItemIds(this List<Item> list)
{
return list.Select(i => i.ID);
}
}
CSharpNoob
Updated on June 29, 2022Comments
-
CSharpNoob almost 2 years
Consider this,
class Item { public string ID { get; set;} public string Description { get; set; } } class SaleItem { public string ID { get; set;} public string Discount { get; set; } } var itemsToRemoved = (List<Item>)ViewState["ItemsToRemove"]; // get only rows of ID var query = from i in itemsToRemoved select i.ID; var saleItems= (List<SaleItem>)ViewState["SaleItems"]; foreach (string s in query.ToArray()) { saleItems.RemoveItem(s); }
How can I write this LINQ phrase using IEnumerable/List Extension methods
// get only rows of ID var query = from i in items select i.ID;
thanks in advance.
-
CSharpNoob over 13 yearsthanks Jon. i have another question, which is faster, the enumerator's extension methods or LInQ queries?
-
Jon Skeet over 13 years@CsharpNoob: The difference only exists in source code. The compiled form is exactly the same.
-
CSharpNoob over 13 yearsi though the RemoveAll extension method evaluates only a single argument.in my example the ID is per Item so i need to iterate each item because they have different IDs
-
Mark Byers over 13 years@CSharpNoob: Could you use hashSet.Contains as your predicate?
-
Mark Byers over 13 years@CSharpNoob: What is List.RemoveItem anyway? My version of .NET doesn't have this method. Is it an extension method you wrote?
-
CSharpNoob over 13 yearsyes I wrote that extension method it has List.FindIndex() inside then it removes the item by the List.RemoveAt() method. like on my example, it only needs to know the string ID to remove the item on the list unlike the built in Remove/RemoveAll method, you have to pass an Instance of the item.
-
Mark Byers over 13 years@CSharpNoob: RemoveAll doesn't need to be passed an instance of the item -it needs only to be passed a predicate (function) that decides whether or not each item should be removed.
-
CSharpNoob over 13 yearspublic static void RemoveItem(this List<Item> items, string itemId) { if (items!= null) { int itemIndex = items.FindIndex(delegate(Item b) { return b.ID.Equals(itemId, StringComparison.Ordinal); }); if (!(itemIndex < 0)) { items.RemoveAt(itemIndex); } } }
-
CSharpNoob over 13 years@mark oh yeah, only the Remove method not the RemoveAll, however even if I replace RemoveItem with RemoveAll, I still need to iterate because of the ID parameter.
-
CSharpNoob over 13 yearsnow I realize, RemoveAll and my RemoveItem method functions the same, thanks dude.
-
Mark Byers over 13 years@CSharpNoob: See this very similar question: stackoverflow.com/questions/4312437/…
-
CSharpNoob over 13 yearswow works like a charm: HashSet<string> itemIds = new HashSet<string>(((List<Item>)ViewState["ItemsToRemove"]).Select(s => s.ID)); saleItems.RemoveAll(c => itemIds.Contains(c.ID));
-
Mark Byers over 13 years@CSharpNoob: Yes, exactly. I've added your code to my answer and rewritten it slightly to make it more readable. Hope that's OK.
-
Pauli Østerø over 13 yearsreading your blogpost i fail to see why its really THAT odd... all you have to accept is that the select-clause will call the Select method on the "thing" specified in the in-clause. The compiler can't bother to care what the thing is, as long as it has a Select method.
-
Jon Skeet over 13 years@Pauli: It doesn't have have to be a Select method though - it can be a property or field of a delegate type. You don't think that's even slightly weird? Likewise the fact that the source can just be the name of a type (so that a static method gets called) seems pretty odd to me.
-
Pauli Østerø over 13 yearsDefining a func to a property/field basically makes it callable with the syntax Select(), tricking the caller to make it look like a method, so i don't find it so weird. And if the compiler doesn't bother with what thing we're specifying in the in-clause, a delegate, a type of a variable is all acceptable as long as they have a Select method or property/field named Select of the type Func.