简体   繁体   中英

Can I write this .NET foreach loop shorter?

I think there is a shorter way of writing this foreach loop that creates a deep copy of a SortedDictionary<string, object> . Note that object is just a place holder, I'm really using some other reference type there. Thanks!

Here is the code:

foreach (KeyValuePair<string, object> entry in sortedDictionary)
{
    this.mSortedDictionary.Add(entry.Key, new object());
}

Whats the point, this is perfectly short.

And for the record, you can make an extension method for Dictioary (or IDictioary) that does this. From then on, you can call the extension method on any dictioary.

mSortedDictionary = sortedDictionary.ToDictionary(kvp => kvp.Key, kvp => new Object());

One of the rules of thumb of programming: in every other loop, there is a catamorphism (also called fold , reduce , inject:into: or inject ) waiting to get out. This is also the case here. Thankfully, one of the LINQ operators provides a catamorphism for us, which Microsoft calls Aggregate :

sortedDictionary.Aggregate(mSortedDictionary, (d, e) => {
    d.Add(e.Key, Transform(e.Value)); return d; });

Note: this could be further simplified by using the K combinator and a destructuring bind. Unfortunately, I couldn't find the K combinator in the BCL, although I'm pretty sure it has to be there somewhere. (If anybody knows, please tell me.)

For the purpose of this example, I'm going to provide my own K combinator and I'm going to call it Tap for no other reason than that's what it's called in Ruby:

public static T Tap<T>(this T o, Action<T> f) { f(o); return o; }

That's literally all there is to it. (Well, at least if you ignore thread-safety and exceptions …)

Using the K combinator, we arrive at this:

sortedDictionary.Aggregate(mSortedDictionary, (d, e) => d.Tap(dd =>
    dd.Add(e.Key, Transform(e.Value))));

Which is much easier on the eye.

Unfortunately, we cannot add destructuring bind ourselves, but if C# did support destructuring bind, it would look more like this:

sortedDictionary.Aggregate(mSortedDictionary, (d, {k, v}) => d.Tap(dd =>
    dd.Add(k, Transform(v))));

[Note: in this example, I use object initializer syntax for destructuring bind.]

For example, in Ruby, which does have both destructuring bind and the K combinator, it would look like this:

sorted_dictionary.reduce(m_sorted_dictionary) {|d, (k, v)|
  d.tap {|d| d[k] = transform(v) }
}

获取nVentive Umbrella Extensions库( http://umbrella.codeplex.com ),然后:

sortedDictionary.ForEach(s => mSortedDictionary.Add(s, new object()));
foreach( string key in sortedDictionary.Keys ) {
   mSortedDictionary.Add(key, new object());
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM