Is there something like LINQ select in D?
I want to remove from a container all elements contained in the member of objects in a given array. I thought it would be nice if I could do:
myContainer.remove( myArray.select!( a => a.member ) ) ;
It is called map:
import std.algorithm;
myContainer.remove(myArray.map!(a => a.member));
Related
I have an object View model which has Id field in the properties. My ID are in following form:
001_001
001_002
002_001
002_002
002_003
002_004
003_001
and so on... I want to sort the data but when I sort it sort thinking it string.
So, what I want is it should sort it as int. So, I have following linq query:
ObjectViewModels.OrderBy ( ids => ids.id )
.GroupBy ( s => int.Parse (s.Id.ToString().Split (new string[] {"_"}, StringSplitOptions.None)[1] ) ).ToList ( ) ;
But it does not seem to work. Thanks for the help.
You can use OrderBy then re-sort using ThenBy.
I'm not sure why you do the GroupBy so I didn't add it to the example
ObjectViewModels.OrderBy(x => int.Parse(x.ID.ToString().Split('_')[0]))
.ThenBy(y => int.Parse(y.ID.ToString().Split('_')[1]));
So I have a list(table) of about 100k items and I want to retrieve all values that match a given list.
I have something like this.
the Table Sections key is NOT a primary key, so I'm expecting each value in listOfKeys to return a few rows.
List<int> listOfKeys = new List<int>(){1,3,44};
var allSections = Sections.Where(s => listOfKeys.Contains(s.id));
I don't know if it makes a difference but generally listOfKeys will only have between 1 to 3 items.
I'm using the Entity Framework.
So my question is, is this the best / fastest way to include a list in a linq expression?
I'm assuming that it isn't better to use another .NETICollection data object. Should I be using a Union or something?
Thanks
Suppose the listOfKeys will contain only small about of items and it's local list (not from database), like <50, then it's OK. The query generated will be basically WHERE id in (...) or WHERE id = ... OR id = ... ... and that's OK for database engine to handle it.
A Join would probably be more efficient:
var allSections =
from s in Sections
join k in listOfKeys on s.id equals k
select s;
Or, if you prefer the extension method syntax:
var allSections = Sections.Join(listOfKeys, s => s.id, k => k, (s, k) => s);
Linq Select method takes Func as input parameter. This means I can have multiple statements in selector for Select, such as
var myresult = sources.Select(s =>
{int x; if (s.val = high) {x=1} else if (s.val = med) {x=2} else {x=3}; return x;
}
)
How can I do this using Linq query syntax
var myresult = from s in sources
select ...
Here, the code in Func part (if ... else if .. else) is artificial. What I really want to know is the syntax of select clause, which may be described as
select select-expression
What is the syntax of
select-expression
I wouldn't want to see your first version in my code. If you need to have what is basically a full function in the lambda, I would rather see the lambda simply invoke a full function! In other words...
theQuery.Select(s => GetX(s)); // just define a GetX function
And that would also be a straightforward translation to query expression syntax
from s in sources
select GetX(s);
You would not be able to put your full code block into the query expression syntax. You could translate your given logic to something usable (yet messy), however I'm quite sure your snippet is just a general example. On the offhand change it isn't, you might try
select s.val == high ? 1 : (s.val == med ? 2 : 3); // totally messy
Instead of special-casing values, with the if/else equivalent of a switch statement, it is more Linq-friendly to group and filter your values:
var myResult = from s in sources
group by s.val into g
select new { Val = g.Key, Sources = g };
var groupHigh = myResult.Where(i => i.Val == high);
var groupMedium = myResult.Where(i => i.Val == medium);
var groupOther = myResult.Except(groupHigh.Concat(groupMedium));
Note that the code I've provided is just a starting place, and isn't the best way to achieve your specific goal. I'd address this in one of these ways:
Change how group by is used (use SomeFunction(s.Val) instead of directly using s.Val)
Change the code around this query to flow better with the natural groupings, so I didn't require the groups to be transformed
This is not possible.
If you really want to, you could create an Func<T> from an anonymous method and invoke it, but that would be horrible.
MSDN indicates select is a contextual keyword of C# 4.0. So I checked the C# Language Specififcation 4.0. Its Select clauses section (7.16.2.5) specifies that
A query expression of the form
from x in e select v
is translated into
( e ) . Select ( x => v )
except when v is the identifier x, the translation is simply
( e )
As the result, the syntax for
select select-expresion
select-expression should be anything that can be used as TResult in Select Method. So the functionality can be done using anonymous Func in Select method may not be able to achieved using select clause.
Conclusion is that you should stick with Method syntax as this is how the code really runs behind the scene.
I am using using Microsoft .NET Framework 4.0.
I have run into this using Aggregate on a Dictionary<T, List<T>> to extract the set of type T values used across all type List<T> lists in the dictionary. Here is the simplest case I could come up with that exhibits the same behaviour.
First, as the documentation states, the following does work:
var set = new HashSet<int>();
var list = new LinkedList<int>();
var newSet = set.Union(list);
That is, I can call Union on a HashSet with a List as the argument (since it implements IEnumerable).
Whereas, the equivalent expression within a Func argument of the LINQ Aggregate expression produces an error (precompiler at least):
new List<int>[] { new List<int>() }.Aggregate(new HashSet<int>(), (acc, list) => acc.Union(list));
It expects the argument of Union to be HashSet, and will cooperate if it is given one, contrary to its behaviour outside LINQ/Func expressions.
The real world example I was using when I came across the problem was:
public AdjacencyListGraph(Dictionary<TVertex, LinkedList<TVertex>> adjacencyList)
{
var vertices = adjacencyList.Aggregate(new HashSet<TVertex>(),
(vertices, list) => vertices.Union(list.Value));
}
Which complains that it cannot convert IEnumerable<TVertex> to HashSet<TVertex>...
The problem here is in your understanding of the Select method. The lambda passed in does not recieve the list but instead elements of the list. So the variable you've named list is in fact of type int which is not compatible with Union.
Here is a more explicit example of what you're trying to do
new List<int>().Select( (int list) => new HashSet<int>().Union(list));
With the type infererence removed it's much clearer why this doesn't work.
The problem actually lies in trying to replace the accumulator type of HashSet with the IEnumerable, .Union method doesn't add items to HashSet, but returns the new IEnumerable on the resulting union.
You should change your code to the following:
// select from keys
var vertices = new HashSet<TVertex>(adjacencyList.Keys);
or
// select from values
var vertices = new HashSet<TVertex>(adjacencyList.SelectMany(dictEntry => dictEntry.Value));
new List<int>().Select(list => new HashSet<int>().Union(list));
I think you would expect to use SelectMany here, unless you want the result to be IEnumerable<IEnumerable<T>>.
I'm trying to retrieve a list of Id's from a collection that is a few levels deep in an object heirachy. When i try to do a ToList(), I keep getting an EntityList<> retrieved instead .. which means it's not allowing me to retrieve an instance's BarId property because the EntitySet is a Enumerable, not a single instance object.
Foo.Child1 (1 to 1)
Child1.Children2 (0 to many of type Bar)
Bar.BarId int;
IList<Foo> fooList = (from blah blah blah).ToList();
var children2List = (from x in fooList
select x.Child1.Children2).ToList();
It keeps returning children2List as an EntitySet<Bar>, not an IList<Bar>. As such, i'm struggling to retrieve the list of BarId's from children2List.
please help!
Your can use:
var children2List = fooList.SelectMany( x => x.Child1.Children2 ).ToList();
This will allow you to do something like:
children2List.ForEach( b => b.BarId.Print() );
In your query, you turn the whole result into a list, not the individual Children2 sets.
Try
var children2List = (from x in fooList
select x.Child1.Children2.ToList()).ToList();
This will turn each Children2 into a List.
EntitySet<T> implements IList<T>, so you already are returning IList<Bar>.