views:

229

answers:

7

string to build up using keyvaluepair is like this: "name1=v1&name2=v2&name3=v3"

what i am doing:

var sb = new StringBuilder();

foreach (var name in nameValues)
{
            sb.AppendFormat("{0}={1}&", name.Key, name.Value);
 } 

//remove last '&' sign, this is what i think is ugly
sb.ToString().Remove(lastIndex);

any elegant way to avoid the last removal statement of '&' sign?

+1  A: 

Well at least you can remove the & sign before the ToString() call by doing --sb.Length;

Gregory Pakosz
+4  A: 
foreach (var name in nameValues)
    {
        if (sb.Length > 0) sb.Append("&");
                sb.AppendFormat("{0}={1}", name.Key, name.Value);
     }

Just add "&" when needed, do not remove it from end.

Nick43
And if speed is a concern, use sb.Append(name.Key).Append("=").Append(name.Value);
Will
+5  A: 

Take a look here: How to build a query string for a URL in C#?; Quoting:

private string ToQueryString(NameValueCollection nvc)
{
    return "?" + 
        string.Join("&", 
            Array.ConvertAll(
                nvc.AllKeys, 
                key => String.Format("{0}={1}", HttpUtility.UrlEncode(key),
                HttpUtility.UrlEncode(nvc[key]))));
}
Rubens Farias
cuil! this will look more cool if accessed as extension method.
this. __curious_geek
is there a NameValueCollection that can hold string,object pair?
Benny
Can't you to use a `Dictionary<string, object>` ?
Rubens Farias
@Rubens, right Dictionary.
Benny
A: 
var sb = new StringBuilder();

sb.AppendFormat("{0}={1}", nameValues[0].Key, nameValues[0].Value);

for (int i = 1; i < nameValues.Count; i++)
{
        sb.AppendFormat("&{0}={1}", nameValues[i].Key, nameValues[i].Value);
} 
Oded
Will
+3  A: 

Here's another approach which I've sometimes used:

var sb = new StringBuilder();
string prefix = "";
foreach (var name in nameValues)
{
    sb.Append(prefix);
    prefix = "&";
    sb.AppendFormat("{0}={1}", name.Key, name.Value);
}

It's just a way of prepending & before every pair other than the first one without using a conditional test.

If you want to use your original idea of trimming the StringBuilder by the way, I'd suggest the following code instead:

sb.Length--; // Remove the last character
return sb.ToString();
Jon Skeet
cool, sb.Length-- is more effective.
Benny
Rubens Farias
+17  A: 
var joined =
    String.Join("&", nameValues.Select(n => n.Key + "=" + n.Value).ToArray());

Given that we're not concatenating to one big string (we're producing many small strings) concatenation carries no performace penalties in this case. And in .NET strings are length prefixed anyway so the whole concatenation performance issue is less relevant than in C. String.Join() is very fast as well, faster than StringBuilder.

TLDR: Use String.Join()

DrJokepu
You forgot the "n =>" in the Select.var joined = String.Join("
helium
helium: Yeah I know I've fixed it. I'm not 100% woken up yet.
DrJokepu
cool. join is amazing
Benny
+3  A: 

I tend to use this, utilising the fact you can truncate a string builder with a decrement on the length property:

var sb = new StringBuilder();

foreach (var name in nameValues)
{
    sb.AppendFormat("{0}={1}&", name.Key, name.Value);
} 

if (sb.Length > 0) sb.Length--;
Rob Levine