Combine Lambda Expressions: The And and the Or

Found this post here but wanted to make a really simple example to demonstrate this.

The idea is simple, take something like this:

currentItem => currentItem.BooleanMethodOne() && currentItem.BooleanMethodTwo()

but say you only want to have one clause or both. Well you could make three separate expressions, but what if you wanted to add even more later? What if you wanted to mix and match? What if you’re reading thing because you watched to see what page could possibly be on the last page of a google search? Well I have answers… stolen answers.

First the needed And and Or methods:

public static Expression<Func<T, Boolean>> And<T>(
   Expression<Func<T, Boolean>> expressionOne,
    Expression<Func<T, Boolean>> expressionTwo
)
{
  //Basically this is like a bridge between the two expressions.  It will take the T
  //parameter from expressionOne and apply it to expression two. So if 
  // oneItem => oneItem.OneMethod() is expressionOne
  // twoItem => twoItem.TwoMethod() is expressionTwo
  //it would be like replacing the twoItem with the oneItem so that they now point
  //to the same thing.
  var invokedSecond = Expression.Invoke(expressionTwo, expressionOne.Parameters.Cast<Expression>());

  //Now this is to create the needed expresions to return.  It will take both early expressions
  //and use the item from the first expression in both.
                    
  //It will look something like this:
  //currentItem => (currentItem.OneMethod And Invoke(currentItem => currentItem.TwoMethod()))
  //As you can see, it looks to be running expressionOne and then a new method that basically
  //calls expressionTwo with the same value (currentItem)
  return Expression.Lambda<Func<T, Boolean>>(
   Expression.And(expressionOne.Body, invokedSecond), expressionOne.Parameters
  );
}

public static Expression<Func<T, Boolean>> Or<T>(
Expression<Func<T, Boolean>> expressionOne, 
Expression<Func<T, Boolean>> expressionTwo
)
{
  var invokedSecond = Expression.Invoke(expressionTwo, expressionOne.Parameters.Cast<Expression>());

  return Expression.Lambda<Func<T, Boolean>>(
   Expression.Or(expressionOne.Body, invokedSecond), expressionOne.Parameters
  );
}

And here’s a test for it:

String[] list;

list = new String[] { "a", "b", "c", "ac", "ab", "cc", "d", "dd", "dc" };

Expression<Func<String, Boolean>> stringLikeA = currentString => currentString.Contains("a");
Expression<Func<String, Boolean>> stringLikeB = currentString => currentString.Contains("b");
Expression<Func<String, Boolean>> stringLikeC = currentString => currentString.Contains("c");

Expression<Func<String, Boolean>> neededUser = And<String>(stringLikeA, stringLikeB);
list.Where(neededUser.Compile());

//a
Assert.IsTrue(list.Where(neededUser.Compile()).Count() == 1);  //ab

//a, c, ac, ab, cc, dc
neededUser = Or<String>(stringLikeA, stringLikeC);

Assert.IsTrue(list.Where(neededUser.Compile()).Count() == 6);

//ab, c, ac, cc, dc
neededUser = And<String>(stringLikeA, stringLikeB);
neededUser = Or<String>(neededUser, stringLikeC);
Assert.IsTrue(list.Where(neededUser.Compile()).Count() == 5);

USINGS!!ONEONE

using System;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.VisualStudio.TestTools.UnitTesting;

Solve FizzBuzz Using Linq Extension Methods

So if you haven’t heard of the FizzBuzz test, it’s basically taking in a list of numbers and figuring out if they are divisible, cleanly, by two numbers. Say you have 3 and 5 and this is your list:

1

3

5

10

15

If the number is divisible by 3, then return the Fizz string. If the number is divisible by 5, return a Buzz string. If it’s divisible by both, then return FizzBuzz.

1

Fizz

Buzz

Buzz

FizzBuzz

Pretty simple and in actuality pretty easy to do with old C# tools, but I wanted to do this with Linq. With the use of Funcs, Actions, and Linq extension methods it can be done fairly easily. Technically you can do the whole thing in one line if you don’t want to bother with refactoring.

I have no idea how to format this cleanly, so sorry if the format is confusing. Basically it is take a list, get the ones you want, concatenate it with the next list.

public static IList<KeyValuePair<Int32, String>> ConvertListOfIntegersWithLinqMethods(IList<Int32> listToConvert, Int32 fizzNumber, Int32 buzzNumber)
{
var result =
  listToConvert
    .Where(WhereBothDivisible(fizzNumber, buzzNumber))
    .Select(selectKeyValuePair("FizzBuzz"))
    .Concat(
  listToConvert
    .Where(WhereBuzzDivisable(fizzNumber, buzzNumber))
    .Select(selectKeyValuePair("Buzz")))
    .Concat(
  listToConvert
    .Where(WhereFizzDivisable(fizzNumber, buzzNumber))
    .Select(selectKeyValuePair("Fizz")))
    .Concat(
  listToConvert
    .Where(WhereNeitherDivisable(fizzNumber, buzzNumber))
    .Select(selectKeyValuePair("Nothing")));

 return result.ToList().OrderBy(currentItem => currentItem.Key).ToList();
}

Using these:

private static Func<Int32, KeyValuePair<Int32, String>> selectKeyValuePair(String value)
{
 return currentItem => new KeyValuePair<Int32, String>(currentItem, value);
}

private static Func<Int32, Boolean> WhereBothDivisible(Int32 fizzNumber, Int32 buzzNumber)
{
 return  currentItem => IsDivisible(currentItem, fizzNumber) && IsDivisible(currentItem, buzzNumber);
}

private static Func<Int32, Boolean> WhereFizzDivisable(Int32 fizzNumber, Int32 buzzNumber)
{
 return currentItem => IsDivisible(currentItem, fizzNumber) && !IsDivisible(currentItem, buzzNumber);
}

private static Func<Int32, Boolean> WhereBuzzDivisable(Int32 fizzNumber, Int32 buzzNumber)
{
 return currentItem => !IsDivisible(currentItem, fizzNumber) && IsDivisible(currentItem, buzzNumber);
}

 private static Func<Int32, Boolean> WhereNeitherDivisable(Int32 fizzNumber, Int32 buzzNumber)
{
 return currentItem => !IsDivisible(currentItem, fizzNumber) && !IsDivisible(currentItem, buzzNumber);
}

When is a field not a field?

Ok so for the last few things I’ve been showing a more dynamic approach to linq queries , mostly dealing with collections rather than say linq to sql. Now take the new method:

public List<K> SelectFromUserList<K, L>(Func<User, K> selectMethod, Func<User, L> orderBy, List<User> userList)
{
    List<K> userList = new List<K>();
    userList = userList.OrderBy(orderBy).Select(selectMethod).ToList();

    return userList;
}

and the call was this:

  List<String> newList = userList.Select(selectUser => selectUser.Name, orderUser => orderUser.ID, userList);

Let’s say you have two needs, selecting all the userNames and all the IDs. You could go ahead and call that method twice and inserting the lambda expressions. But let’s say you want to be able to mix and match things. Say select user names and order by user id or maybe select user names and order by use names. Well there’s a solution to avoid rewriting the lambda expressions:

  Func<User, Int32> selectUserID = currentUser => currentUser.UserID;
  Func<User, String>selectUserName = currentUser => currentUser.UserName;

  Func<User, Int32> orderByUserID = currentUser => currentUser.UserID;
  Func<User, String> orderByUserName = currentUser => currentUser.UserName;

What the? See a while ago I had a method to pass back the expression, but in this case there’s nothing to create the expression from (a passed in parameter) since they are really simple expressions. How would I use them?

  List<Int32> userIDs;
  List<User> userList;
  List<String> userNames;
  userIDs = SelectFromUserList(selectUserID, orderByUserID, userList);
  userNames = SelectFromUserList(selectUserName, orderByUserID, userList);

Pretty nice huh?

Adding to the Select

So in the last post there was something like this:

 public List<K> SelectUserNameList<K>(Func<User, K> selectMethod, List<User> userList)
 {
   return userList.Select(selectMethod, userList).ToList();
 }

Called by this:

 List<String> newList = userList.Select(user => user.Name, userList);

Ok so what if you want to order something? Well same idea, just another Func. But remember, a Func that can order by any type. If you look at the OrderBy method, it expects a Func<User, L> where L is just some type you are returning. If you were ordering by UserID, well that would be an integer. Problem is, like select, you don’t want to be held down by a specific type.

 public List<K> SelectFromUserList<K, L>(Func<User, K> selectMethod, Func<User, L> orderBy, List<User> userList)
 {
   List<K> userList = new List<K>();

   userList = userList.OrderBy(orderBy).Select(selectMethod).ToList();

   return userList;
 }

And the new call would be:

 List<String> newList = userList.Select(selectUser => selectUser.Name, orderUser => orderUser.ID, userList);

Now something of note is the order in which you call the methods. Remember, x.OrderBy().Select() is saying take collection X, order it by L and create a new collection of X, then select whatever you want. You can not do the reverse. Say you want to select a list of UserNames ordered by UserName. Well you can either:

1) Order the list by user name in a list of users then select the user names.

2) Select a list of user names into a list of strings, order that list by a string.

What if you want to select user names but order by user id? You can:

1) Order the list by user id and create a list of users then select the user names.

2) Select a list of user names into a list of string and… eh LOSE

Best part about:

 userList = userList.Select(selectMethod).OrderBy(orderBy).ToList();

Is that the error is somewhat misleading. It gives you the “Cannot be inferred by usage” error, not the “Idiot, you can’t order a list of Strings by UserID”. So you have to be careful on how you have things in order.

Speaking of Select

So like Where and other fine Extension methods, Select allows you to either give it a lambda expression like so:

  List<String> newList = userList.Select(user => user.Name);

Or

  List<Int32> newList = userList.Select(user => user.ID);

So either you get a list of Names or IDs. What the hell do you care? Well if you are capable of breathing, you should also notice that one list is a list of strings the other a list of integers. What if you wanted a generic select method? Well for starters you would do something like this:

public List<String> SelectFromUserList(Func<User, String> selectMethod, List<User> userList)
{
  return userList.Select(selectMethod).ToList();
}

Where the select method for a user name would be something like this:

  List<String> nameList = SelectFromUserList(currentUser => currentUser.UserName, userList);

Sweet… oh wait, that only works if I want a list strings. Great if I wanted LastName, FirstName, ect but sucks if I wanted an integer ID.

  List<String> nameList = SelectFromUserList(currentUser => currentUser.UserID, userList); //BOOM

But wait, you can do that!

public List<K> SelectUserNameList<K>(Func<User, K> selectMethod, List<User> userList)
{
  return userList.Select(selectMethod).ToList();
}

Aw snap, now I can get a list of anything I want, well at least a one type, one dimensional array. By the way, this is the first step in probably a series of posts that will end up with a much cleaner way of doing this.

Linq query versus just a Select

Something I ran into using the Ajax.dll and AjaxMethods (Or basically the idea of being able to call a method from .cs file in javascript) is that when returning a list of Users there was difficulty in serialization. Basically, if you have a list of users that contain a list of roles that contain a list of permissions that contain seven wives with seven children with seven dogs and seven cats… Basically a lot of information. Now lazy loading should take care of this, but lets assume there is no lazy loading.(No idea what would cause that…) Well you have an awful lot to pushout to the front end. Let’s just say it can be a little sluggish. Lets assume you are just sending the list out, and you’ve already done all the querying.

You could do:

 return userList;

Which is what I was doing. Kind of slow.

You could do:

 var query = from user in userList
             select new
             {
                UserName = user.UserName,
                UserID = user.ID
             };

 return query.ToList();

Nothing wrong with that, just a bit verbose for something so simple.

You could do this:

 return userList.Select(currentItem => new { Username = currentItem.UserName, UserID = user.ID });

All in one line. Now I personally like the sql-ish linq expressions, but for this why not fit it into one line?

Match Collections Using Linq Union

So let’s say you have two lists you want to compare to see if they hold the same items, but the items are not equal reference. Now, if you are comparing two lists that have unique values to compare, Union is perfect.

List 1 { 1, 2, 3, 4, 5 }

List 2 { 2, 1, 4, 3, 5 }

As you can see, there are no repeated values in these two lists. Easy way to figure out if all the values are the same in the two lists:

  var query = (from first in firstList
            select first).Union(from second in secondlist
                                select second);

  Assert.IsTrue(query.Count() == first.Count());

Why does this work? Union combine the two lists, removing any duplicates. So if everything goes correctly, the count of the new list has to match the count of either of the olds lists. After all 5 pairs of duplicate items gets reduced to a list of 5. Now, if there is anything different between the lists the count will get screwed. Why? Because even one difference will cause an extra item to show up in the list.

List 1 { 1, 2, 3, 4, 5 }

List 2 { 1, 2, 3, 4, 6 }

Union { 1, 2, 3, 4 , 5, 6 }

And it will only get worse for every mismatch.

Real worldish example:

    var query = (from user in userListFirst
              select user.UserID).Union(from secondUser in userListSecond
                                       select second.UserID);

    Assert.IsTrue(query.Count() == userListFirst.Count());

Bonus points if you can figure out why this would fail at times. Actually, I already told you…

UsInGS

  using System;
  using System.Linq;

Life is fun when you are slow

public void IfTrueRunMethod(Func<Boolean> trueMethod, Action action)
{
  if(trueMethod())
  {
    action();
  }
}

Just something I made for the hell of it to remove:

if(someClass != null && someClass.Property == "hi")
{
  SomeMethod();
}

This can be reduced to one line… yay!

IfTrueRunMethod(() => { someClass != null && someClass.Property == "hi" }, () => SomeMethod());

You could even transform the first part into a method if you want:

IfTrueRunMethod(() => TrueMethod(someClass), () => SomeMethod());

Weeeee!

using System;
using System.Linq;

I’m starting to worry about myself

So the “dynamic” linq query so far isn’t just enough to stop. Oh no, now that I can have methods pass back expressions, what about a dictionary of order by expressions to allow an even more dynamic feel? Huh? How’s about that kids? I hate myself too.

//Enum created for the dictionary key
public enum OrderByChoice
{
  FirstName,
  LastName,
  UserName
}

//dictionary of expressions
private static Dictionary<OrderByChoice, Expression<Func<User, String>>>  GetOrderByList()
{
  if(orderByList == null)
  {
    orderByList = new Dictionary<OrderByChoice,Expression<Func<User, String>>>();

    orderByList.Add(OrderByChoice.FirstName, currentUser => currentUser.FirstName);
    orderByList.Add(OrderByChoice.LastName, currentUser => currentUser.LastName);
    orderByList.Add(OrderByChoice.UserName, currentUser => currentUser.UserName);
  }

  return orderByList;
}

That’s right, I know. Silly, but I think it’s cool. Now mind you, I could have methods that return expressions instead of the expressions themselves, but I wanted to show the expressions.

And for the method call:

public static IList<User> GetUserList(OrderByChoice orderBy)
{
  return GetUserList(currentUser => true, GetOrderByList()[orderBy]).ToList();
}

And now you have an even more dynamicish call.

I FORGOT THE USINGS!!!!

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Linq.Expressions;

And some days I love programming

This is the newest edition of Linq madness. So I added an OrderBy to my lame dynamic query thing.

private static IQueryable<User> GetUserList(Expression<Func<User, Boolean>> whereClause, Expression<Func<User, String>> orderBy)
{
    var query = (from user in GetDataContext().Users
             select user).Where(whereClause).OrderBy(orderBy);

    return query;
}

Now you will notice there is a new Expression in town and it’s name isn’t Reggie Hammond. It is my order by Expression which uses a Func<User, String>. It took me a minute to figure out how this works. I thought it was somehow in need of the property name to order by, but in reality it is looking for a list of strings to order by. Simple. I could do something like: (Ignore the WhereLikeFirstNameLastNameUserName for now)

    return GetUserList
           (
            WhereLikeFirstNameLastNameUserName(name),
            currentUser => currentUser.UserName
           ).ToList();

But that’s boring. I want to be able to pass a method that would give the correct string to orderby somewhat cleaner. In comes a method that returns an Expression. OooOoOOo.

private static Expression<Func<User, String>> SortOnUserName()
{
    return currentUser => currentUser.UserName;
}

So now it looks like:

public static IList<User> GetUserListByLikeName(String name)
{
   return GetUserList
          (
           WhereLikeFirstNameLastNameUserName(name),
           SortOnUserName()
          ).ToList();
}

Cleaner… Now what is WhereLikeFirstNameLastNameUserName? Simple, that is my where Expression just being returned in this method:

private static Expression<Func<User, Boolean>> WhereLikeFirstNameLastNameUserName(String name)
{
   return currentUser => SqlMethods.Like(currentUser.UserName, "%" + name + "%")
   || SqlMethods.Like(currentUser.FirstName, "%" + name + "%")
   || SqlMethods.Like(currentUser.LastName, "%" + name + "%");
}

By the way, SqlMethods.Like is just a built in method used only with Linq to Sql. Probably shouldn’t have used it in this example but oh well. Live with it.

OH NO NOT THE USINGS!!

using System;
using System.Collections.Generic;
using System.Data.Linq.SqlClient;
using System.Linq;
using System.Linq.Expressions;