Just a little niggle about LINQ syntax. I'm flattening an IEnumerable<IEnumerable<T>> with SelectMany(x => x).
My problem is with the lambda expression x => x. It looks a bit ugly. Is there some static 'identity function' object that I can use instead of x => x? Something like SelectMany(IdentityFunction)?
Unless I misunderstand the question, the following seems to work fine for me in C# 4:
public static class Defines
{
public static T Identity<T>(T pValue)
{
return pValue;
}
...
You can then do the following in your example:
var result =
enumerableOfEnumerables
.SelectMany(Defines.Identity);
As well as use Defines.Identity anywhere you would use a lambda that looks like x => x.
Note: this answer was correct for C# 3, but at some point (C# 4? C# 5?) type inference improved so that the IdentityFunction method shown below can be used easily.
No, there isn't. It would have to be generic, to start with:
public static Func<T, T> IdentityFunction<T>()
{
return x => x;
}
But then type inference wouldn't work, so you'd have to do:
SelectMany(Helpers.IdentityFunction<Foo>())
which is a lot uglier than x => x.
Another possibility is that you wrap this in an extension method:
public static IEnumerable<T> Flatten<T>
(this IEnumerable<IEnumerable<T>> source)
{
return source.SelectMany(x => x);
}
Unfortunately with generic variance the way it is, that may well fall foul of various cases in C# 3... it wouldn't be applicable to List<List<string>> for example. You could make it more generic:
public static IEnumerable<TElement> Flatten<TElement, TWrapper>
(this IEnumerable<TWrapper> source) where TWrapper : IEnumerable<TElement>
{
return source.SelectMany(x => x);
}
But again, you've then got type inference problems, I suspect...
EDIT: To respond to the comments... yes, C# 4 makes this easier. Or rather, it makes the first Flatten method more useful than it is in C# 3. Here's an example which works in C# 4, but doesn't work in C# 3 because the compiler can't convert from List<List<string>> to IEnumerable<IEnumerable<string>>:
using System;
using System.Collections.Generic;
using System.Linq;
public static class Extensions
{
public static IEnumerable<T> Flatten<T>
(this IEnumerable<IEnumerable<T>> source)
{
return source.SelectMany(x => x);
}
}
class Test
{
static void Main()
{
List<List<string>> strings = new List<List<string>>
{
new List<string> { "x", "y", "z" },
new List<string> { "0", "1", "2" }
};
foreach (string x in strings.Flatten())
{
Console.WriteLine(x);
}
}
}
With C# 6.0 and if you reference FSharp.Core you can do:
using static Microsoft.FSharp.Core.Operators
And then you're free to do:
SelectMany(Identity)
With C# 6.0 things are getting better. We can define the identity function in the way suggested by #Sahuagin:
static class Functions
{
public static T It<T>(T item) => item;
}
And then use it in SelectMany the using static constructor:
using Functions;
...
var result = enumerableOfEnumerables.SelectMany(It);
I think it looks very laconic in the such way. I also find the identity function useful when building dictionaries:
class P
{
P(int id, string name) // Sad. We are not getting primary constructors in C# 6.0
{
ID = id;
Name = id;
}
int ID { get; }
int Name { get; }
static void Main(string[] args)
{
var items = new[] { new P(1, "Jack"), new P(2, "Jill"), new P(3, "Peter") };
var dict = items.ToDictionary(x => x.ID, It);
}
}
This may work in the way you want. I realize Jon posted a version of this solution, but he has a second type parameter which is only necessary if the resulting sequence type is different from the source sequence type.
public static IEnumerable<T> Flatten<T>(this IEnumerable<T> source)
where T : IEnumerable<T>
{
return source.SelectMany(item => item);
}
You can get close to what you need. Instead of a regular static function, consider an extension method for your IEnumerable<T>, as if the identity function is of the collection, not the type (a collection can generate the identity function of its items):
public static Func<T, T> IdentityFunction<T>(this IEnumerable<T> enumerable)
{
return x => x;
}
with this, you don't have to specify the type again, and write:
IEnumerable<IEnumerable<T>> deepList = ... ;
var flat = deepList.SelectMany(deepList.IdentityFunction());
This does feel a bit abusive though, and I'd probably go with x=>x. Also, you cannot use it fluently (in chaining), so it will not always be useful.
I'd go with a simple class with a single static property and add as many as required down the line
internal class IdentityFunction<TSource>
{
public static Func<TSource, TSource> Instance
{
get { return x => x; }
}
}
SelectMany(IdentityFunction<Foo>.Instance)
Related
I'm trying to do the reverse of the Select method: to project bunch of items based on their Id,
I'm thinking of Where so I would make something like this:
db.Books.Where(b => b.Id==1 || b.Id==3 || b.Id==5)
but if I have a long list of Id, or if I want to search by Title , it will be very painful code,
so is there a way to retrieve a list of items based on a group of values (like SQL: WHERE id IN..)
string[] bookNames = { "BookName1", "BookName2" };
db.Books.Where(b => bookNames.Contains(b.Name));
The solutions listed above all work - Dispersia's LINQ query's really nice actually.
One more possibility to keep in mind for what it's worth: you can always write your own LINQ-like extension methods. Here are a couple I put together for what they're worth. (I don't claim that these are actually better than the other solutions or that you'd necessarily want to use them instead - they're just something to keep in mind for reference in case you want to do something similar in the future).
Note that the compiler'll even allow you to add them to the System.Linq namespace if you want, but you could definitely argue about whether that's a good practice or not.
namespace System.Linq
{
public static class LinqExtensions
{
// This one's more or less like "Contains" except for the "params" part
// Example: book.Id.In(1, 2, 3, 4, 5)
public static bool In<T>(this T item, params T[] list)
{
foreach (T args in list)
{
if (args.Equals(item))
{
return true;
}
}
return false;
}
// Same idea as above except using an equality tester
// Example: listBooks.Where(book => book.In((bk, id) => bk.Id == id, 1, 2, 3, 4, 5));
public static bool In<T, U>(this T item, Func<T, U, bool> equalitytester, params U[] list)
{
foreach (U arg in list)
{
if (equalitytester(item, arg))
{
return true;
}
}
return false;
}
// See if any item in the first list is also in the second list
public static bool In<T, U>(this IEnumerable<T> list, Func<T, U, bool> equalityTester, params U[] argList)
{
foreach (T item in list)
{
foreach (U arg in argList)
{
if (equalityTester(item, arg))
{
return true;
}
}
}
return false;
}
}
}
You can declare a List<integer> or an array of integers. Add values to it. AND USE Contains method
Where(b => lst.Contains(b))
I' wrote an extension method, and it works great as I wanted, with any type and any member:
public static IEnumerable<TSource> In<TSource, TMember>(this IEnumerable<TSource> source,
Func<TSource, TMember> identifier, params TMember[] values) =>
source.Where(m => values.Contains(identifier(m)));
You can call it like this:
var myBooks = Books.In(b => b.Id, 1, 3, 5, 8, 11, 22);
For my future needs, I uploaded it to NuGet
Install-Package Mshwf.NiceLinq
I wanted to create an extension method that would efficiently wrap single objects as IEnumerables. This was to avoid the cases where you end up putting a new [] {} in the middle of an expression. This is easy enough to do using the following method:
public static IEnumerable<TSource> WrapAsEnumerable<TSource>(this TSource source)
{
return new[] { source };
}
The problem is that this will be applied to any and all types (which is the expected behavior), but this will also have the side effect of making the method available on IEnumerable <T> instances. In the case where the resolved extended type is an IEnumerable<T>, I would simply like to return this IEnumerable, since the aternative is finding myself with a IEnumerable<IEnumerable<T>>, which is not really what you'd expect when calling the method.
Instinctively (and perhaps sleepily), I first created an overload that looked like this
public static IEnumerable<TSource> WrapAsEnumerable<TSource>(this IEnumerable<TSource> source)
{
return source;
}
in order to handle the case where the type to wrap is an IEnumerable<T>, But of course, the control flow always resolves to the first method.
So, the question is: how could I create such a wrapping method that handles both the case where the extended parameter instance is an IEnumerable<T> and when it is not ?
Here is another attempt, inspired from Eric Lippert's excellent post at: https://stackoverflow.com/a/1451184/4955425.
You can control the overloading resolution by placing your 2 extension methods at different levels in the namespace hierarchy.
namespace MyExtensions
{
public static class HighPrecendenceExtensions
{
public static IEnumerable<TSource> WrapAsEnumerable<TSource>(this IEnumerable<TSource> source)
{
return source;
}
}
namespace LowerPrecedenceNamespace
{
public static class LowPrecedenceExtensions
{
public static IEnumerable<TSource> WrapAsEnumerable<TSource>(this TSource source)
{
return new[] { source };
}
}
}
}
However, the downside is that you'll always need to refer to both namespaces to get the right method invocation behavior.
using MyExtensions;
using MyExtensions.LowerPrecedenceNamespace;
Have you considered changing your signature a little bit, makes the code a little more complicated but makes the usage extremely simple.
public static class Extensions
{
public static IEnumerable<TSource> WrapAsEnumerable<TSource>(this object source)
{
var allInterfaces = source.GetType().GetInterfaces();
IEnumerable<Type> allEnumerableInterfaces = allInterfaces.Where(t => t.Name.StartsWith("IEnumerable"));
if (!allEnumerableInterfaces.Any())
return new[] { (TSource)source };
IEnumerable<Type> genericEnumerableOfTSource = allEnumerableInterfaces.Where(t => t.GenericTypeArguments.Contains(typeof(TSource)));
// we have a generic implementation
if (genericEnumerableOfTSource.Any())
{
return (IEnumerable<TSource>) source;
}
return new[] { (TSource)source }; ;
}
}
[TestFixture]
public class Tests
{
[Test]
public void should_return_string_an_enumerable()
{
const string aString = "Hello World";
var wrapped = aString.WrapAsEnumerable<string>();
wrapped.ShouldAllBeEquivalentTo(new[] {"Hello World"});
}
[Test]
public void should_return_generic_enumerable_unwrapped()
{
var aStringList = new List<string> { "Hello", "World" };
var wrapped = aStringList.WrapAsEnumerable<string>();
wrapped.ShouldAllBeEquivalentTo(new[] { "Hello", "World" });
}
[Test]
public void should_return_non_generic_enumerable_unwrapped()
{
var aStringArray = new[] {"Hello", "World"};
var wrapped = aStringArray.WrapAsEnumerable<string>();
wrapped.ShouldAllBeEquivalentTo(new[] { "Hello", "World" });
}
}
I have a toy implementation of a Maybe monad in C# and have implemented the relevant SelectMany extension methods to work with Linq. I stumbled upon a problem when I tried to mix IEnumerable and IMaybe in a single Linq statement.
The Maybe monad looks like
public interface IMaybe<T>
{
bool HasValue { get; }
T Value { get; }
}
public static class Maybe
{
class SomeImpl<T>: IMaybe<T> // obvious implementation snipped for brevity
class NoneImpl<T>: IMaybe<T> // obvious implementation snipped for brevity
// methods to construct the Maybe monad
public static Wrap<T> Some<T>(T value);
public static Wrap<T> Some<T>(T? value) where T: struct;
public static IMaybe<T> None<T>();
public static IMaybe<B> SelectMany<A, B>(this IMaybe<A> a, Func<A, IMaybe<B>> mapFn)
{
if (a.HasValue)
return mapFn(a.Value);
else
return None<B>();
}
public static IMaybe<C> SelectMany<A, B, C>(
this IMaybe<A> a, Func<A, IMaybe<B>> mapFn, Func<A, B, C> selector)
{
if (a.HasValue)
{
var b = mapFn(a.Value);
if (b.HasValue)
return Some(selector(a.Value, b.Value));
else
return None<C>();
}
else
return None<C>();
}
}
My program tries to read a file, parse the content into a number of URI entries, and for each of the entries download the content from the URI. Exactly how these operations are implemented is irrelevant. The trouble I have lies in the chaining these operations in a Linq statement. I.e.
static IMaybe<string> ReadFile(string path);
static IMaybe<KeyValuePair<string, Uri>[]> ParseEntries(string input);
static IMaybe<string> Download(Uri location);
static void Main(string[] args)
{
var result = // IEnumerable<IMaybe<anonymous type of {Key, Content}>>
from fileContent in ReadFile(args[0])
from entries in ParseEntries(fileContent)
from entry in entries // this line won't compile
from download in Download(entry.Value)
select new { Key = entry.Key, Content = download };
// rest of program snipped off for brevity
}
The error in question complains about mixing the IMaybe and IEnumerable monads. In its exact wording:
Error 1 An expression of type 'System.Collections.Generic.KeyValuePair[]' is not allowed in a subsequent from clause in a query expression with source type 'MonadicSharp.IMaybe'. Type inference failed in the call to 'SelectMany'. C:\Dev\Local\MonadicSharp\MonadicSharp\Program.cs 142 31 MonadicSharp
How do I get around this?
It seems to me that the issue lies in the signature for ParseEntries.
It currently is:
static IMaybe<KeyValuePair<string, Uri>[]> ParseEntries(string input);
Perhaps it should be?
static IMaybe<KeyValuePair<string, Uri>>[] ParseEntries(string input);
So instead of a maybe of array it should be an array of maybe.
I think the issue is because entries is of type IMaybe<T> and not of type IEnumerable<T>.
Have you tried something like this:
from entry in entries.Value
Of course this is not what the purpose of a Monad is, but this should be the first step.
After some research I've concluded that it is just impossible to mix monads in a single LINQ statement so I decided to break it into two statements. This is how it works:
First off, I need to make a slight change to the IMaybe interface declaration to use covariance:
public interface IMaybe<out T>{ ... }
Next, I need some helper method to transform the IMaybe monad to the IEnumerable monad:
public static IEnumerable<IMaybe<T>> UnfoldAll<T>(
this IMaybe<IEnumerable<T>> source)
{
if (source.HasValue)
return Enumerable.Range(0, 1).Select(i => Maybe.None<T>());
else
return source.Value.Select(value => Maybe.Some(value));
}
And finally, I will break the original LINQ statement into two statements (nesting LINQ expressions works too)
static void Main(string[] args)
{
var path = args[0];
var theEntries =
from fileContent in ReadFile(path)
from entries in ParseEntries(fileContent)
select entries;
var theContents =
from entry in theEntries.UnfoldAll()
where entry.HasValue
select Download(entry.Value.Value);
foreach (var content in theContents)
{
//...
}
}
As you can see, the first LINQ statement works on IMaybe monad and the second one on the IEnumerable.
I would like something like this:
public int NumberStudent()
{
int i = 0;
if (db.Tbl_Student.ToList().Count() > 0)
i = db. Tbl_Student.Max(d => d.id);
return i;
}
However, I would like to use it on any table:
public int FindMaxId(string TableName)
{
int i =0;
if ('db.'+TableName+'.ToList().Count() > 0' )
i = db. TableName.Max(d => d.id);
return i ;
}
I know it is wrong, but I'm not sure how to do it.
You can use the IEnumerable/IQueryable extension method DefaultIfEmpty for this.
var maxId = db.Tbl_Student.Select(x => x.Id).DefaultIfEmpty(0).Max();
In general, if you do Q.DefaultIfEmpty(D), it means:
If Q isn't empty, give me Q; otherwise, give me [ D ].
Below I have written a simple wrapper around the existing Max extension method that allows you provide an empty source (the table you were talking about).
Instead of throwing an exception, it will just return the default value of zero.
Original
public static class Extensions
{
public static int MaxId<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int> selector)
{
if (source.Any())
{
return source.Max(selector);
}
return 0;
}
}
This was my attempt, which as noted by Timothy is actually quite inferior. This is because the sequence will be enumerated twice. Once when calling Any to check if the source sequence has any elements, and again when calling Max.
Improved
public static class Extensions
{
public static int MaxId<TSource>(this IQueryable<TSource> source, Func<TSource, int> selector)
{
return source.Select(selector).DefaultIfEmpty(0).Max();
}
}
This implementation uses Timothy's approach. By calling DefaultIfEmpty, we are making use of deferred execution and the sequence will only be enumerated when calling Max. In addition we are now using IQueryable instead of IEnumerable which means we don't have to enumerate the source before calling this method. As Scott said, should you need it you can create an overload that uses IEnumerable too.
In order to use the extension method, you just need to provide a delegate that returns the id of the source type, exactly the same way you would for Max.
public class Program
{
YourContext context = new YourContext();
public int MaxStudentId()
{
return context.Student.MaxId(s => s.Id);
}
public static void Main(string[] args)
{
Console.WriteLine("Max student id: {0}", MaxStudentId());
}
}
public static class Extensions
{
public static int MaxId<TSource>(this IQueryable<TSource> source, Func<TSource, int> selector)
{
return source.Select(selector).DefaultIfEmpty(0).Max();
}
}
db.Tbl_Student.Aggregate(0, (maxId, s) => Math.Max(maxId, s.Id))
or
db.Tbl_Student.Max(s => (int?)s.Id) ?? 0
I have a requirement to modify a method so that it has an extra parameter that will take a lambda expression that will be used on an internal object to return the value of the given property. Forgive my probable incorrect use of terminology as this is my first foray into LINQ expressions!
I have tried searching for an answer, but as I mentioned, my terminology seems to be off and the examples I can find are far too complex or deal with expressions for collection functions such as .Where(), which I am familiar with.
What I have so far (cut down version):
class MyClass
{
private MyObject _myObject = new MyObject() { Name = "Test", Code = "T" };
private string MyMethod(int testParameter, ??? selector)
{
//return _myObject.Name;
//return _myObject.Code;
return ???;
}
}
I would like to call it something like this:
string result = _myClassInstance.MyMethod(1, (x => x.Name));
or:
string result = _myClassInstance.MyMethod(1, (x => x.Code));
Obviously the parts which I am missing is the selector parameter in MyMethod, how to apply it to the local variable and how to pass the required property into the method when I am invoking it.
Any help would be appreciated, also extra bonus points for a VB.NET solutions as well as unfortunately the final implementation needs to be in our lone VB project!
private string MyMethod(int testParameter, Func<MyObject, string> selector)
{
return selector(_myObject);
}
When using Func delegates, the last parameter is the return type and the first N-1 are the argument types. In this case, there is a single MyObject argument to selector and it returns a string.
You can invoke it like:
string name = _myClassInstance.MyMethod(1, x => x.Name);
string result = _myClassInstance.MyMethod(1, x => x.Code);
Since the return type of MyMethod matches the return type of your selector delegate, you could make it generic:
private T MyMethod<T>(int testParameter, Func<MyObject, T> selector)
{
MyObject obj = //
return selector(obj);
}
I don't know VB.Net but it looks like it would be:
Public Function MyMethod(testParameter as Integer, selector as Func(Of MyObject, String))
Return selector(_myObject)
End Function
and the generic version would be:
Public Function MyMethod(Of T)(testParameter as Integer, selector Func(Of MyObject, T))
Return selector(_myObject)
End Function
I will show you a different approach that is very flexible (see DotNetFiddle at the bottom): You can easily write your own LINQ functions to extend existing functions or write your own functions and benefit from the power of LINQ queries.
In this example, I am improving Linq's Distinct function in a way so you can specify a field, which is used for grouping.
Usage (Example):
var myQuery=(from x in Customers select x).MyDistinct(d => d.CustomerID);
In this example the query is being grouped by CustomerID and the first element of each group is returned.
Declaration of MyDistinct:
public static class Extensions
{
public static IEnumerable<T> MyDistinct<T, V>(this IEnumerable<T> query,
Func<T, V> f)
{
return query.GroupBy(f).Select(x=>x.First());
}
}
You can see that f, the 2nd parameter, is declared as Func<T, V>, so it can be used by the .GroupBy statement.
Coming back to the code in your question, if you have declared
class MyObject
{
public string Name;
public string Code;
}
private MyObject[] _myObject = {
new MyObject() { Name = "Test1", Code = "T"},
new MyObject() { Name = "Test2", Code = "Q"},
new MyObject() { Name = "Test2", Code = "T"},
new MyObject() { Name = "Test5", Code = "Q"}
};
you could use that with the newly defined function MyDistinct as follows:
var myQuery = (from x in _myObject select x).MyDistinct(d => d.Code);
which will return
Name Code
Test1 T
Test2 Q
or you can use .MyDistinct(d => d.Name) in the query, which returns:
Name Code
Test1 T
Test2 Q
Test5 Q
Notice that because MyDistinct is declared with the generics T and V, it recognizes and uses the right object types automatically and returns MyObject elements.
Advanced usage
Notice that MyDistinct always takes the first element of each group. What if you need a condition defining which element you need?
Here's how you can do it:
public static class Extensions
{
public static IEnumerable<T> MyDistinct<T, V>(this IEnumerable<T> query,
Func<T, V> f,
Func<IGrouping<V,T>,T> h=null)
{
if (h==null) h=(x => x.First());
return query.GroupBy(f).Select(h);
}
}
This modification either allows you to use it exactly as before, i.e. by specifying one parameter like .MyDistinct(d => d.Name), but it also allows you to specify a having condition such as x => x.FirstOrDefault(y => y.Name.Contains("1")||y.Name.Contains("2")) as a second parameter like so:
var myQuery2 = (from x in _myObject select x).MyDistinct(d => d.Name,
x=>x.FirstOrDefault(y=>y.Name.Contains("1")||y.Name.Contains("2"))
);
If you run this query, the result is:
Name Code
Test1 T
Test2 Q
null
because Test5 does not meet the condition (it does not contain 1 or 2), you're getting null in the 3rd row.
Note: If you want to expose just the condition, you can have it even simpler by implementing it as:
public static IEnumerable<T> MyDistinct2<T, V>(this IEnumerable<T> query,
Func<T, V> f,
Func<T,bool> h=null
)
{
if (h == null) h = (y => true);
return query.GroupBy(f).Select(x=>x.FirstOrDefault(h));
}
In this case, the query would just look like:
var myQuery3 = (from x in _myObject select x).MyDistinct2(d => d.Name,
y => y.Name.Contains("1") || y.Name.Contains("2")
);
so you don't need to write x=>x.FirstOrDefault(... condition ...).
Try it in DotNetFiddle
in C#
The parameter type you are looking for Func
private string MyMethod(int testParameter, Func<MyClass,string> selector){
return selector(_myObject);
}
in VB you still want Func the syntax is a little different.
Function MyMethod(ByVal testParameter As Integer, ByVal selector as Func(Of MyClass,string) as string
return selector(_myObject)
End Function
class MyClass
{
private MyObject _myObject = new MyObject() { Name = "Test", Code = "T" };
private string MyMethod(int testParameter, Func<MyObject, string> selector)
{
return selector(_myObject );
}
}
You can do that with a delegate of your selector:
delegate string SampleDelegate(MyObject obj);
private string MyMethod(int testParameter, SampleDelegate selector)
{
return selector(_myObject);
}
You are probably looking for the Delegate class ("Delegate" in VB, "delegate" in C#), or one of its subtypes.
This page has some examples you will probably find useful, especially near the bottom of the page.
Here is a VB example of what you would want to do:
Public Class MyClass
Private Property _myObject As MyObject = New MyObject With {.Name = "Test", .Code = "T"}
Private Function MyMethod(testParameter As Integer, selector As Func(Of MyObject, String)) As String
Return selector(_myObject).ToString
End Function
End Class