I have a function as follow. I need to return two parameters. First the index that is as list and it is done by the function. The other parameter that I need to return is a string str.
What would be your best suggestion for these outputs? a list with two different parameters? or what? Please let me know your ideas! Thanks
public List<int> index_selexted(TreeNodeCollection treeView, List<int> list)
{
List<int, List<string>> output_typ = new List<int, >();
foreach (TreeNode node in treeView)
{
if (node.Checked)
{
list.Add(node.Index);
string str = Regex.Match(node.Text, #" \((.*?)\) ").Groups[1].Value;
}
else
{
index_selexted(node.Nodes, list);
}
}
return list;
}
Well, since TreeNode.Index is not unique within the entire TreeNodeCollection then Dictionary<int, String> is not a choice, but Dictionary<int, List<String>> will do
//TODO: find a better name for dict
public Dictionary<int, List<String>> index_selexted(
TreeNodeCollection treeView,
Dictionary<int, List<String>> dict == null) { // == null for autocreation
if (null == treeView)
throw new ArgumentNullException("treeView");
if (null == dict)
dict = new Dictionary<int, List<String>>();
foreach (TreeNode node in treeView)
if (node.Checked) {
String match = Regex.Match(node.Text, #" \((.*?)\) ").Groups[1].Value;
List<String> list;
if (dict.TryGetValue(node.Index, out list))
list.Add(match);
else
dict.Add(node.Index, new List<String>() {match});
}
else
index_selexted(node.Nodes, dict);
return dict;
}
And so you'll have something like this as an output: index + all matches for it:
{1, ["abc", "def", "gh"]}
{3, ["xyz"]}
I've added dict == null in order to make the call easier:
// You don't have to pre-create the dictionary
var myDict = index_selexted(myTreeView.Nodes);
Use a Tuple
var res = new Tuple<string, List<string>>("string1", new List<string>());
You could either do
public class IndexSelectionResult{
public List<something> Index{get;set;}
public String StringResult
}
and return an instance of that, OR, if you're lazy, you can return a TUPLE:
public Tuple<List<string>, string>> myFunction(){ /* code */}
I believe you want this:
public static List<int> index_selexted(TreeNodeCollection treeView, out string str)
{
str = null;
var list = new List<int>();
var output_typ = new List<int>();
foreach (TreeNode node in treeView)
{
if (node.Checked)
{
list.Add(node.Index);
str = Regex.Match(node.Text, #" \((.*?)\) ").Groups[1].Value;
}
else
{
index_selexted(node.Nodes, list);
}
}
return list;
}
usage as such:
var treeview = sometreeview;
string output;
var result = index_selected(treeview, out output);
Console.WriteLine(output);
instead of using the list in your example (List> output_typ = new List();) consider
using a dictionary:
var output_typ = new Dictionary<int, List<string>>();
or a list of tuples:
var output_typ = new List<Tuple<int, List<string>>();
Hope this helps
There are a lot of ways to do this in fact, it depends on your specific use case which one you'd prefer.
Using a class
class MyResult {
public List<int> MyList { get; set; }
public string MyString { get; set; }
}
public MyResult index_selected(arg1..., arg2...) {
return new MyResult {
MyList = outputList,
MyString = "outputString"
}
}
Using a class is my preferred way. Though it may clutter if you have many return types it is by far the most readable solution.
Using a tuple
public Tuple<List<int>, string> index_selected(arg1..., arg2...) {
return Tuple.Create(outputList, "outputString");
}
My second goto option is a tuple. It is a lot more difficult to determine what the values contained in the tuple represent. But doesn't require creating more classes and is a quick solution (I use it mostly for private methods where readability is not much of a concern).
Using the out keyword
public List<int> index_selected(arg1..., out string resultString) {
resultString = null;
/* Doing calculations and such */
resultString = "
return outputList;
}
In this case the string passed to the resultString parameter will be replaced by whatever you assign to it in the method (see out keyword). Depending on your use case you may also want to look at the ref keyword.
This approach is rather error prone and is generally not preffered.
Related
I've following method in the code.I could have some more if conditions in the future.
So just wondering how to re-factor this code from a maintenance point of view.
string MyMethod(string filter)
{
StringBuilder sbFilter = new StringBuilder(filter);
if (filter.Contains("A"))
{
sbFilter.Append("X");
}
if (filter.Contains("B"))
{
sbFilter.Append("Y");
}
if (filter.Contains("C"))
{
sbFilter.Append("Z");
}
return sbFilter.ToString();
}
Thanks.
You can put your from/to combinations into an array, which can easily be modified.
With linq you can select the values:
String FilterMethod(String filter) {
var fromTo = new[] {"A,X","B,Y","C,Z"};
return String.Concat(
from pair in fromTo
let split= pair.Split(',')
where split.Length == 2 && filter.Contains(split[0])
select split[1]
);
}
You can even make a one-liner:
String FilterMethod2(String filter) {
return String.Concat(
from pair in new[] { "A,X", "B,Y", "C,Z" }
let split = pair.Split(',')
where split.Length == 2 && filter.Contains(split[0])
select split[1]
);
}
You could simply use a list of tuples:
KeyValuePair<string, string>[] mappings = new []
{
new KeyValuePair<string, string>("A", "X"),
new KeyValuePair<string, string>("B", "Y"),
new KeyValuePair<string, string>("C", "Z"),
};
string MyMethod(string filter)
{
var sbFilter = new StringBuilder(filter);
foreach (var m in mappings)
{
if (filter.Contains(m.Key))
sbFilter.Append(m.Value);
}
return sbFilter.ToString();
}
Which can be written even more concisely using LINQ:
string MyMethod(string filter)
{
return filter + string.Concat(mappings
.Where(m => filter.Contains(m.Key))
.Select(m => m.Value));
}
As # Jakub DÄ…bek wrote in his comment, this question is more suitable for code review forum, but I think that using a SortedDictionary will make your code more maintainable and clear. that way you will never have the need to change MyMethod function. based on your example, i would do something like that (please see my comments inside the code):
private SortedDictionary<string, string> _Dic;
public SortedDictionary<string, string> Dic
{
get
{
if (_Dic == null)
{
_Dic = new SortedDictionary<string, string>();
_Dic.Add("A", "X");
_Dic.Add("B", "Y");
_Dic.Add("C", "Z");
// add more key-pair values in the future
return _Dic;
}
else
{
return _Dic;
}
}
set
{
// important: here you can get your valus from external source!
_Dic = value;
}
}
string MyMethod(string filter)
{
StringBuilder sbFilter = new StringBuilder(filter);
foreach (KeyValuePair<string, string> itm in Dic)
{
if (filter.Contains(itm.Key))
{
sbFilter.Append(Dic[itm.Key]);
}
}
return sbFilter.ToString();
}
I have a Dictionary<string, string> used to match a string to a new one.
Dictionary<string, string> dictionary = new Dictionary<string, string>()
{
{ "foo", "bar" }
};
The method I use to match the string:
public static string GetValueOrKeyAsDefault(this Dictionary<string, string> dictionary, string key)
{
string value;
return dictionary.TryGetValue(key, out value) ? value : key;
}
Used like so:
string s1 = dictionary.GetValueOrKeyAsDefault("foo"); /* s1 equals "bar" */
string s2 = dictionary.GetValueOrKeyAsDefault("test"); /* s2 equals "test" */
I now want to match a string partially and keep part of this string in the matched one.
/* {0} is arbitrary, could be anything else */
Dictionary<string, string> dictionary = new Dictionary<string, string>()
{
{ "SPROC:{0}", "{0}" },
{ "onClick='{0}(this)'", "{0}" }
};
string s1 = dictionary.SomeMethod("SPROC:my_sproc"); /* s1 equals "my_sproc" */
string s2 = dictionary.SomeMethod("onClick='HandleOnClick(this)'"); /* s1 equals "HandleOnClick" */
I feel like regex could be a way but I have no idea how to implement it.
Note that using a Dictionary<,> here is "morally" wrong... I would use a List<Tuple<Regex, string>>. It is morally wrong for two reasons: the ordering (so the priority) of the various key-values isn't "fixed" and could be quite random AND you can't leverage on the strength of the Dictionary<,>: the O(1) exact match (TryGetValue).
Still:
public static string SomeMethod(Dictionary<string, string> dictionary, string str)
{
foreach (var kv in dictionary)
{
var rx = new Regex(kv.Key);
if (rx.IsMatch(str))
{
string replaced = rx.Replace(str, kv.Value);
return replaced;
}
}
return str;
}
Dictionary<string, string> dictionary = new Dictionary<string, string>()
{
{ #"SPROC:(.*)", "$1" },
{ #"onClick='(.*)\(this\)'", "$1" }
};
string replaced = SomeMethod(dictionary, "SPROC:my_sproc");
Note that you have to use the Regex "language" (see the (.*) and the $1)
Without the useless Dictionary<,>:
public static string SomeMethod(IEnumerable<Tuple<Regex, string>> tuples, string str)
{
foreach (var rr in tuples)
{
if (rr.Item1.IsMatch(str))
{
string replaced = rr.Item1.Replace(str, rr.Item2);
return replaced;
}
}
return str;
}
var dictionary = new[]
{
Tuple.Create(new Regex("SPROC:(.*)"), "$1"),
Tuple.Create(new Regex(#"onClick='(.*)\(this\)'"), "$1"),
};
string replaced = SomeMethod(dictionary, "SPROC:my_sproc");
As a sidenote, I would add a ^ at the beginning of each regex and a $ at the end of each regex, like "^SPROC:(.*)$", just to be sure that the regex won't match partial substrings.
I create a list first
List<String> dummy1 = new List<String>();
List<String> dummy2 = new List<String>();
List<String> dummy3 = new List<String>();
List<String> dummy4 = new List<String>();
Before I add the list to Dictionary
Dictionary<int, List<String>> _d = new Dictionary<int, List<String>>()
{
{1, dummy1},
{2, dummy2},
{3, dummy3},
{4, dummy4},
};
then I want to have the name of the list by looping the key
foreach (var key in _d.Keys)
{
MessageBox.Show(_d[key].GetType().Name);
}
but the output is list 1, I want to get the
dummy1
dummy2
dummy3
dummy4
As I commented, you can only do this with really funky syntax. Here's an example of what I mean
void Main()
{
List<String> dummy1 = new List<String>();
List<String> dummy2 = new List<String>();
List<String> dummy3 = new List<String>();
List<String> dummy4 = new List<String>();
var _d = new Dictionary<int, Expression<Func<List<String>>>>()
{
{1, () => dummy1},
{2, () => dummy2},
{3, () => dummy3},
{4, () => dummy4},
};
foreach(var kvp in _d)
{
MessageBox.Show(kvp.Value.nameof());
}
}
// Define other methods and classes here
public static class TestExtension
{
public static String nameof<T>(this Expression<Func<T>> accessor)
{
return nameof(accessor.Body);
}
public static String nameof<T, TT>(this T obj, Expression<Func<T, TT>> propertyAccessor)
{
return nameof(propertyAccessor.Body);
}
private static String nameof(Expression expression)
{
if (expression.NodeType == ExpressionType.MemberAccess)
{
var memberExpression = expression as MemberExpression;
if (memberExpression == null)
return null;
return memberExpression.Member.Name;
}
return null;
}
}
The main issue is that you need the dictionary to store an expression, rather than a List
Secondly, to actually ACCESS the list, you need to do this:
var list = _d[1].Compile()();
And lastly, if dummy1 ever gets reassigned, you'll lose the reference to the list you're expecting.
In short, it's very unlikely that you need to do this. It's rare that the variable names in code should actually affect behaviour.
You are assigning data to a variable name and you are going to get the variable name in order to access the data. I would create a simple object with a Name and List and add it to the Dictionary.
Just make a custom class that inherits from List<string> and have a Name property.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
MyList dummy1 = new MyList("dummy1");
MyList dummy2 = new MyList("dummy2");
MyList dummy3 = new MyList("dummy3");
MyList dummy4 = new MyList("dummy4");
Dictionary<int, MyList> _d = new Dictionary<int, MyList>()
{
{1, dummy1},
{2, dummy2},
{3, dummy3},
{4, dummy4},
};
foreach (var key in _d.Keys)
{
Console.WriteLine(_d[key].Name);
}
}
}
public class MyList : List<String>
{
private string name;
public string Name
{
get
{
return name;
}
}
public MyList(string name)
{
this.name = name;
}
}
Results:
dummy1
dummy2
dummy3
dummy4
Demo
Instead of creating a Dictionary that stores an int and a list:
Dictionary<int, List<String>>
Create a Dictionary that stores the name of the list with the list:
Dictionary<string, List<String>>
If you want to then get the int number that corresponds to the list, you can use a normal for loop and see what value is at the location when let's say i = 1.
public class MyClass
{
public MyClass()
{
myDictionary = new Dictionary<string, string>();
myArray = new List<int>();
}
private Dictionary<string, string> myDictionary;
public Dictionary<string, string> MyDictionary
{
get { return myDictionary; }
}
private List<int> myArray;
public List<int> MyArray
{
get { return myArray; }
}
}
static void Main(string[] args)
{
var model = new MyClass();
Type t = model.GetType();
System.Reflection.PropertyInfo[] properties = t.GetProperties();
//Add items to MyArray and MyDictionary in this model According to the properties using reflection
}
I want to add items to MyArray and MyDictionary in this model According to the properties using reflection.
Thank you for your help !
var dictProp = properties.Single(t => t.Name = "MyDictionary");
var myDict = (Dictionary<string,string>)dictProp.GetValue(model, null);
myDict.Add("MyKey", "MyValue");
To add an Item to a Generic.List<T> you use the Add method
Example:
MyArray.Add(1);
For Generic.Dictonary<T> you also use the Add method, but supply 2 values, Key and Value
MyDictionary.Add("MyKey", "MyValue");
So you can just loop though your PropertyInfo[] and add whatever you need to your List<T> or Dictionary<T>
foreach(var prop in properties )
{
MyArray.Add(a number from somewhere);
MyDictionary("some key", "some value");
}
I need to store daily statistics in the isolated storage of Windpws Phone which leads me to believe that a multidimensional dictionary would be the most useful but I'm having trouble wrapping my head around the logic needed to get this to work.
The stats looks something like this in pseudocode:
dictionary DailyStats {
1,
[Stats] => dictionary {
[Class] => 5,
[Entertainment] => 3,
[Personnel] => 2,
[Price] => 7,
[Quality] => 6
}
}
I started out with this:
var DailyStats = new Dictionary<int, Dictionary<string, string>>();
But as soon as I wanted to assign values to this structure I got lost quite fast. The values are collected by the app for each day.
I've thought of Linq but it seems to be overkill for what I'm trying to do.
Can anyone point me in the right direction?
Thanks!
If you have one dicionary with StatusClasses???
var DailyStats = new Dictionary<int, StatusClass>();
And:
class StatusClass
{
//substitute the vars for their type
var Class;
var Entertainment;
var Personnel;
var Price;
var Quality;
public StatusClass(var ClassValue, var EntertainmentValue, var Personnel.....)
{
Class = ClassValue;
Entertainment = EntertainmentValue;
...........
}
}
If your keys are fixed Daniel's solution is the way to go. If you want to use a dictionary a static class like this might help:
static class DailyStats
{
static Dictionary<int, Dictionary<string, string>> _dic;
static DailyStats()
{
_dic = new Dictionary<int, Dictionary<string, string>>();
}
public static void Add(int i, string key, string value)
{
if (!_dic.ContainsKey(i))
_dic[i] = new Dictionary<string, string>();
_dic[i][key] = value;
}
public static string Get(int i, string key)
{
if (!_dic.ContainsKey(i) || !_dic[i].ContainsKey(key))
return null;
return _dic[i][key];
}
}
DailyStats.Add(1, "Stats", "a");
Console.WriteLine(DailyStats.Get(1, "Stats"));