Archives
Wilsonhut on Flickr
Advertisements
Deal with it or don't
Is your Aggregate throwing an InvalidOperationException: Sequence contains no elements?
This line of code certainly would:
new string[]{}.Aggregate((ag, s) => ag + ", " + s)
Use this instead:
new string[]{}.DefaultIfEmpty("[NA]").Aggregate((ag, s) => ag + ", " + s)
I was writing some extension methods for things such as Aggregate where the only purpose was to pass in default values. That was not very smart, since you can always use DefaultIfEmpty() and pass your default value there. Really, what I needed was an overload of DefaultIfEmpty that takes a Func to get the default value, in case the default value is expensive (a database look-up, for example)
So here that is:
public static IEnumerable<TSource> DefaultIfEmpty<TSource>(this IEnumerable<TSource> source, Func<TSource> getDefaultValue) { using (var enumerator = source.GetEnumerator()) { if (enumerator.MoveNext()) { do { yield return enumerator.Current; } while (enumerator.MoveNext()); } else yield return getDefaultValue(); } }
Now you can say
new string[]{}.DefaultIfEmpty(() => goGetTheDefaultValue()).Aggregate((ag, s) => ag + ", " + s)
This one is even too obvious to comment on:
public static TResult MaxOrDefault(this IEnumerable source, Func selector, TResult defaultValue) { return source.Select(selector).DefaultIfEmpty(defaultValue).Max(); } public static TResult MaxOrDefault(this IEnumerable source, Func selector) { return source.Select(selector).DefaultIfEmpty().Max(); } public static TResult MinOrDefault(this IEnumerable source, Func selector, TResult defaultValue) { return source.Select(selector).DefaultIfEmpty(defaultValue).Min(); } public static TResult MinOrDefault(this IEnumerable source, Func selector) { return source.Select(selector).DefaultIfEmpty().Min(); }
It just makes the code a little more succinct when trying to avoid the InvalidOperationException: Sequence contains no elements
This might not be intuitive to you (it wasn’t to me)
What does the following line return?
Enumerable.Empty<string>().All(t => t == "I don't think so")
…or maybe this would even be more confusing:
Enumerable.Empty<string>().All(t => t != t)
Well… both of those return true. (See Vacuous Truth)
I didn’t want to have to tack a call to Any() in my code for this situation, so I wrote AnyAndAll (which also performs better since it won’t even begin to enumerate the list twice.
Here it is:
You’re welcome.
You want your website’s log4net logs to have the authenticated user’s name. Here’s all you do.
(credit to Gian Marco Gherardi)
Add this in your code (right after you call XmlConfigurator.Configure(…) would be fine.)
GlobalContext.Properties["user"] = new HttpContextUserNameProvider();
Then…
public class HttpContextUserNameProvider { public override string ToString() { HttpContext context = HttpContext.Current; if (context != null && context.User != null && context.User.Identity.IsAuthenticated) { return context.User.Identity.Name; } return ""; } }
The, in your log4net config, you can use it with “%property{user}”
like so…
<conversionPattern value="%date %-5level %property{Category} [%property{user}] - %message%newline" />
Like a charm.
Substring() is fun, right? It’s fun because “Index and length must refer to a location within the string.”
Well, sometimes, you just want the Left few characters. Sometimes, if you chop of the extra length in your string, you want ellipsis to indicate there are missing pieces.
Here you go:
Now, you can use it like so:
“I’m just saying bless your heart.”.Left(14, OverflowBehavior.Ellipsis) will return “I’m just sayin…”
It defaults to ‘None’, so you can just do “I’m just saying bless your heart.”.Left(14) and get “I’m just sayin”
Got data that’s all upper case? All lower case? Want it title case, or proper case?
“WHY AM I SHOUTING?”.ToTitleCase() returns “Why Am I Shouting?”
“the meek shall inherit the earth.”.ToTitleCase() returns “The Meek Shall Inherit The Earth.”
Maybe you just want to know the things from list1 where they have a match in list2.
You can do that yesterday and today with list1.Join(list2, item1=>item1, item2=>item2, (item1,item2)=>item1);
But today and tomorrow, you can simply do list1.Join(list2).
Obvious, right?
So you don’t want to do a ToList(), but you don’t want to enumerate your IEnumerable<T> more than once? How about an extension method called “Cache” that Caches the output as you go.
That’s it. If you want to see it in action, open LINQPad, select Language: “C# Program”, delete everything, paste in the above, then finally, paste in the below:
void Main() { var x = GetNumbers().Cache(); "TAKE 2.".Dump(); x.Take(2).Dump("TWO:"); "Get them all.".Dump(); x.Dump("ALL:"); "Get them all again.".Dump(); x.Dump("ALL:"); } public IEnumerable<T> GetNumbers() { yield return 1.Dump("Numbers is hard"); Thread.Sleep(500); yield return 2.Dump("Numbers is hard"); Thread.Sleep(500); yield return 3.Dump("Numbers is hard"); Thread.Sleep(500); yield return 4.Dump("Numbers is hard"); Thread.Sleep(500); yield return 5.Dump("Numbers is hard"); Thread.Sleep(500); yield return 6.Dump("Numbers is hard"); }
There.
You have an IEnumerable<SomeType> on which you want to do a .Distinct(). “SomeType” is not equatable – at least not in the way you want. Your only choice is to write an IEqualityComparer… Until today!!!
Here’s what you WANT to write:
myEnumerable.Distinct(item => item.Id);
…assuming that the Id’s make them unique. And here’s the extension method override of Distinct that lets you do this:
public static class Extensions
{
public static IEnumerable<T> Distinct<T, TCompare>(this IEnumerable<T> items, Func<T, TCompare> predicate)
{
var distinctKeys = new HashSet<TCompare>();
foreach (var item in items)
{
var key = predicate(item);
if (distinctKeys.Contains(key)) continue;
distinctKeys.Add(key);
yield return item;
}
}
}
Now, you’re probably saying, couldn’t I just write?:
myEnumerable.GroupBy(item => item.Id).Select(g => g.First());
It gives you the same output, but, this new Distinct method is:
var list = new[]
{
new {x = 1, y = “one”},
new {x = 1, y = “won”},
new {x = 1, y = “juan”},
new {x = 0, y = “zero”},
};
…and this call to .Distinct:
list.Distinct(item => 1 / item.x).Take(1);
With the GroupBy approach, this would raise an Exception. But with the new Distinct, you get no exception because it is so dang lazy.
I wrote before about partitioning a string, which was a way to bust a string into Chunks. It used the string like an IEnumerable<char>. I thought it would be nice to be able to Chunk any enumerable (for batching, or whatever).
The Partition was written without regard to performance, but this time, it’s all about performance. Just try to make it faster.
Here’s the extension method:
1 public static class Extensions
2 {
3 public static IEnumerable<IEnumerable<T>> ToChunks<T>(this IEnumerable<T> list, int chunkSize)
4 {
5 var enumerator = list.GetEnumerator();
6
7 for (;;)
8 {
9 var chunk = enumerator.GetNext(chunkSize);
10 if (chunk.Length == 0)
11 {
12 break;
13 }
14 yield return chunk;
15 }
16 }
17
18 private static T[] GetNext<T>(this IEnumerator<T> enumerator, int count)
19 {
20 var ts = new T[count];
21 int i;
22 for (i = 0; i < count; i++)
23 {
24 if (!enumerator.MoveNext()) break;
25 ts[i] = enumerator.Current;
26 }
27 if (i < count)
28 {
29 Array.Resize(ref ts, i);
30 }
31 return ts;
32 }
33 }
When I needed this recently, I also needed to know in each chunk where I was in the original IEnumerable, so instead of returning an IEnumerable of IEnumerables, I returned an IEnumerable of a new Chunk type that inherits from IEnumerable. I just had to make a small change on lines 3, 7, and 14:
1 public static class Extensions
2 {
3 public static IEnumerable<Chunk<T>> ToChunks<T>(this IEnumerable<T> list, int chunkSize)
4 {
5 var enumerator = list.GetEnumerator();
6
7 for (var i = 0;; i++)
8 {
9 var chunk = enumerator.GetNext(chunkSize);
10 if (chunk.Length == 0)
11 {
12 break;
13 }
14 yield return new Chunk<T>(chunk, i*chunkSize, chunk.Length);
15 }
16 }
17
18 private static T[] GetNext<T>(this IEnumerator<T> enumerator, int count)
19 {
20 var ts = new T[count];
21 int i;
22 for (i = 0; i < count; i++)
23 {
24 if (!enumerator.MoveNext()) break;
25 ts[i] = enumerator.Current;
26 }
27 if (i < count)
28 {
29 Array.Resize(ref ts, i);
30 }
31 return ts;
32 }
33 }
34
…and here’s Chunk
1 public class Chunk<T> : IEnumerable<T>
2 {
3 private readonly IEnumerable<T> _chunk;
4
5 public Chunk(IEnumerable<T> chunk, int first, int length)
6 {
7 _chunk = chunk;
8 FirstIndex = first;
9 Length = length;
10 }
11
12 public int FirstIndex { get; private set; }
13 public int Length { get; private set; }
14 public int LastIndex { get { return FirstIndex + Length – 1; } }
15
16 public IEnumerator<T> GetEnumerator()
17 {
18 return _chunk.GetEnumerator();
19 }
20
21 IEnumerator IEnumerable.GetEnumerator()
22 {
23 return GetEnumerator();
24 }
25 }