Use Select method to traverse an IEnumerable in C# - c#

I have the following method that I use to traverse collections like IQueryCollection, IHeadersDictionary and IFormCollection
public static string ToString(IEnumerable<KeyValuePair<string, StringValues>> dic)
{
string res = "";
foreach (var item in dic)
{
res += item.Key + "=" + item.Value + "&";
}
return res.TrimEnd('&');
}
I was wondering if it would be possible to do it in a more " functional" style, using something like Select and String.Join method
I'm using dot-net-core 2.0

Yes you can write it using a select, it's actually quite simple:
public static string ToString(IEnumerable<KeyValuePair<string, StringValues>> dic)
{
return string.Join("&", dic.Select(_ => $"{_.Key}={_.Value}"));
}
Will it perform better, hard to say without testing, your version uses string concatenations which are probably not a good idea for a large number of string (StringBuilder) would be better. But I expect string.Join to do a better job than your version.

You have a few options:
Using Aggregate
dic.Aggregate((res, item) => res + item.Key + "=" + item.Value + "&")
.TrimEnd('&')
Using Select and string.Join
string.Join("&", dic.Select(item => item.Key + "=" + item.Value))
Using Zip and string.Join if you are using a Dictionary instance instead of a list of KeyValuePairs:
string.Join("&", dict.Keys.Zip(dict.Values, (key, value) => key + "=" + value))

You can use
var result = from keyvaluepair in dictionary
from value in keyvaluepair .Value
select keyvaluepair .Key + "=" + value;
or try aggregate,
string result = values.Aggregate("",
(key, pair) =>
key + "=" + pair.Key + ":"
+ pair.Value.Aggregate("",
(str, val) => str + "=" + val)
);
There is already a post related to same in How do I combine the keys and values of a Dictionary into one List using LINQ?

Related

Better ways to convert tuple list to string

I have a List in below structure:
Tuple<string, string>
like this:
And I would like to join the list to form a string like below:
['A', '1'],['B', '2'], ['C', '3']...
And I am now using below code to do:
string result = "";
for (int i = 0; i < list.Count; i++)
{
result += "[ '" + list[i].Item1 + "', '" + list[i].Item2 + "'],";
}
The code works OK, but would like to ask if there're any better ways to do that?
You can make it more compact by using Linq, string.Join and string.Format:
result = string.Join(",", list.Select(t => string.Format("[ '{0}', '{1}']", t.Item1, t.Item2)));
You can do it using linq and string interpolation like this:
string.Join(", ", list.Select(t => $"['{t.Item1}', '{t.Item2}']"));
There are some benchmarking (note: each word contains one link, but one of the best reference I think is this.) on how to join the string.
Quote from the reference:
Rico Mariani, the .NET Performance guru, had an article on this very
subject. It's not as simple as one might suspect.
You could take a look on string.Concat and string.Builder in particular, they are usually faster than + operator.
Here I use string.Concat:
string str = string.Concat(new string[] { "[ '", list[i].Item1, "', '", list[i].Item2, "']," });
This might also do the trick for you
var input = new List<Tuple<string, string>>
{
Tuple.Create("A", "1"),
Tuple.Create("B", "2"),
Tuple.Create("C", "3")
};
string tpljoined = string.Join(", ",
input.Select(x => "['" + x.Item1 + "','" + x.Item2 + "']"));
You can also use LINQ:
var input = new List<Tuple<string, string>> { Tuple.Create("A", "1"), Tuple.Create("B", "2") };
var result = String.Join(",", input.Select(elem => "[ '" + elem.Item1 + "', '" + elem.Item2 + "']"));
Console.WriteLine(result);

How to access subObject properties values in c#

I am trying to loop over an object properties and values and build a string with them.
The problem is i cant seem to access the values of the properties which are not string...
Here is what i have so far:
private string ObjectToStringArray(CustomType initParameters)
{
var stringArray = "";
foreach (var parameter in initParameters.GetType().GetProperties())
{
if (parameter.PropertyType.Name == "String")
stringArray += "\"" + parameter.Name + "\" => \"" + parameter.GetValue(initParameters) + "\",\r\n";
else
{
stringArray += "array(\r\n";
foreach (var subParameter in parameter.PropertyType.GetProperties())
{
stringArray += "\"" + subParameter.Name + "\" => \"" + subParameter.GetValue(parameter) + "\",\r\n";
}
stringArray += "),";
}
}
return stringArray;
}
i can get to the values of all the string properties but one level down i just cant extract the property object itself.
My exception is: System.Reflection.TargetException: Object does not match target type.
When calling subParameter.GetValue(parameter), you are passing a PropertyInfo, whereas you seemingly want to pass the value of that property for initParameters instead.
You should thus pass parameter.GetValue(initParameters) to subParameter.GetValue() instead.

Browse dictionaries with params in C #

I created a method that receives an unspecified amount of dictionaries parameters and scans the content of all of them but the same is not covered, it gives error in the first or second foreach, depending on what I fix. Consegundo'm not fix this problem. How could I make this work paraque.
I get the params dictionary and I want to go through the contents of each.
The code that I follow below:
public String getQuerySelectInner(String TABELA, params Dictionary<String, String> dictionaries)
{
String sql = "SELECT ";
foreach (Object dictionary in dictionaries)
{
foreach (var word in dictionary)
{
sql += word.Key + ",";
}
}
sql = sql.Remove(sql.Length - 1);
sql += " from " + TABELA + " WHERE situacao = 'ATIVO' ";
return sql;
}
Your code doesn't even compile. Are you coding using notepad or an actual IDE?
Anyhow, if you add brackets for your params and change your outer foreach to a var rather than casting to an Object it compiles. Does that help to give you what you want?
public String getQuerySelectInner(String TABELA, params Dictionary<String, String>[] dictionaries)
{
String sql = "SELECT ";
foreach (var dictionary in dictionaries)
{
foreach (var word in dictionary)
{
sql += word.Key + ",";
}
}
sql = sql.Remove(sql.Length - 1);
sql += " from " + TABELA + " WHERE situacao = 'ATIVO' ";
return sql;
}
To further improve things a bit you could use string.join instead of your inner loop: sql += string.Join(",", dictionary.Keys); which means you don't need to remove the extra comma after.

C# - Advanced foreach statements?

I currently have:
string settings = "setting1:value1;setting2:value2";
string[] pair;
foreach(string setting in settings.Split(';'))
{
pair = setting.Split(':');
MessageBox.Show(pair[0] + ":" + pair[1]);
}
I would something more along the lines of:
string settings = "setting1:value1;setting2:value2";
foreach (string[] pair in string setting.Split(':') in settings.Split(';'))
{
MessageBox.Show(pair[0] + ":" + pair[1]);
}
The two in keywords seem a bit ridiculous, but I would think something like this would be possible and very easy, I just don't know how.
So, is it possible?
I'm not sure this is more readable, but you asked for it and I think it looks cool ;-)
string settings = "setting1:value1;setting2:value2";
foreach(var pair in settings.Split(';').Select(str => str.Split(':')))
{
MessageBox.Show(pair[0] + ":" + pair[1]);
}
(I haven't compiled it, so I'm sorry if there are syntax errors)
As an alternative to the other posted answers, you can also use the LINQ syntax:
string settings = "setting1:value1;setting2:value2";
foreach(string[] pair in
from setting in settings.Split(';')
select setting.Split(':'))
{
MessageBox.Show(pair[0] + ":" + pair[1]);
}
foreach (string[] pair in settings.Split(';').Select(setting => setting.Split(':')))
{
MessageBox.Show(pair[0] + ":" + pair[1]);
}
foreach (string settingstr in settings.Split(';'))
{
string[] setval = settingstr.Split(':');
string setting = setval[0];
string val = setval[1];
}

Pass dynamic data type to function

I have the following function:
private string ParseJson(dynamic q)
{
string returnJSON = "[{ \"type\" : \"pie\", \"name\" : \"Campaigns\", \"data\" : [ ";
foreach (var grp in q)
{
double currCount = grp.Count();
if (grp.Key != null)
returnJSON += "['" + grp.Key + "', " + currCount + "],";
else
returnJSON += "['none', " + currCount + "],";
}
returnJSON = returnJSON.Substring(0, returnJSON.Length - 1);
returnJSON += "]}]";
return returnJSON;
}
I call it from methods like this one:
public string GetCampaignData()
{
PaymentModelDataContext db = new PaymentModelDataContext();
var q = from Event in db.TrackingEvents
group Event by Event.campaignID;
return ParseJson(q);
}
I use q for several different queries, all grouping data.
The problem is that the runtime can't bind a type to q for some reason. Is this a proper use of dynamic? Is there a different way to do this?
The problem is Count() is an extension method off of IEnumerable<T>, as such it can't be called from dynamic (because it's not a true method of the class).
Your variable grp is also dynamic because it results from an expression on dynamic variable q:
foreach (var grp in q)
Since we can't call extension methods off of dynamic (again, they aren't true members of the class), we need to explicitly call the extension method instead off the Enumerable static class. So change your code to:
double currCount = Enumerable.Count(grp);
And you'll see it work properly for the Count(), if you want to really use dynamic.
That said, I do agree with #John's comment that you should consider changing this to a non-dynamic. Actually, what your method would accept would be an IEnumerable> like so:
private string ParseJson<TKey,TValue>(IEnumerable<IGrouping<TKey,TValue>> q)
{
string returnJSON = "[{ \"type\" : \"pie\", \"name\" : \"Campaigns\", \"data\" : [ ";
foreach (var grp in q)
{
double currCount = grp.Count();
if (grp.Key != null)
returnJSON += "['" + grp.Key + "', " + currCount + "],";
else
returnJSON += "['none', " + currCount + "],";
}
returnJSON = returnJSON.Substring(0, returnJSON.Length - 1);
returnJSON += "]}]";
return returnJSON;
}
You can also make the parameter type non-generic specific to your usage if you like. But this would work with all groupings...

Categories