8

In Haskell we have the function

map (a -> b) -> [a] -> [b]

to change the type of a Collection using a function.

Is there something similar in C#?

Or what else is the fastest way to put a complete collection of KeyValuePairs into a debug message, for example?

I thought of sth like

debugmsg("http response is " + service.HttpResponseHeaders
                                      .Map<string>((k, v) => k + "->" + v)
                                      .Aggregate((s, sx) => s + "," + sx)
                             + ". ");
1
  • Note that a header can have multiple values. Simply concatenating the value won't work Commented Nov 6, 2013 at 8:23

5 Answers 5

13

In LINQ, map is named Select. Also, please note that any collection of KeyValuePair<TKey, TValue> will have only one argument in Select; you'll have to pull the Key and Value out of it.

service.HttpResponseHeaders.Select(kvp => kvp.Key + "->" + kvp.Value)
                           .Aggregate((s, sx) => s + "," + sx);
Sign up to request clarification or add additional context in comments.

4 Comments

Value is an IEnumerable<string>. Simply concatenating strings will result in "String[]" instead of the actual value
If it's the case (that the Value from key-value pair is a collection), then doing SelectMany a.k.a flatMap on the value should solve the issue.
Not really, you need to combine a single header name with multiple values. A single operation is not enough.
Doing kvp => kvp.Key + "->" + string.Join("-", kvp.Value) should be good enough then. The question was about map though...
1

LINQ comes with Select

Signature (Haskell style):

IEnumerable<TSource>.Select(Func<TSource->TResult>)->IEnumerable<TResult>

Comments

1

As others have noted, you can map one type to another using Select. Creating the final string is best done using String.Join though, to avoid creating useless temporary strings.

Strings in .NET are immutable so adding two strings creates a new string. String.Join on the other hand uses a StringBuilder internally to add data to a mutable buffer and return the final result.

You should note though that HttpResponseHeaders contains multiple values for each key. Just converting the value to a string will not work.

The following will create a comma-separated list of values from the response headers. If the header has multiple values, they are separated by '|':

var headerStrings=from header in service.HttpResponseHeaders
            let headerValue=String.Join("|",header.Value)
            select String.Format("{0} -> {1}",header.Key,headerValue);
var message=String.Join(",",headerStrings);

Comments

1

You could use Dictionary, which is basically a collection of KeyValuePairs and do something like:

service.HttpResponseHeaders
                  .Select(kvp => kvp.Key + " -> " + String.Join(" - ", kvp.Value))
                  .Aggregate((s, sx) => s + ", " + sx);

Optimizing Aggregate: Optimizing Aggregate for String Concatenation

6 Comments

HttpResponseHeaders is also a collection of KeyValuePair, actually it implements IEnumerable<KeyValuePair<string, IEnumerable<string>>>. No need for Dictionary, and string concatenation will return "String[]", not the header value
Then call .Aggregate() on your value. Have a look at my edit.
A String.Join would be simpler and faster, because it wouldn't create any temporary strings
Are you sure .Aggregate() does? Why shouldn't it use the StringBuilder also?
Apart from the DRY, just try it and see how ugly it looks
|
0

You can use .Select() or if it is a List you can use .ConvertAll()

Here is the MSDN Documentation

Enumerable.Select

List.ConvertAll

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.