Converting a string to a variable name - c#

public static string filename2_1, filename2_2, filename2_3;
filename2_1="xyz.jpg";
filename2_2="abc.png";
filename2_3="qwe.jpg";
.....
...
for (int key = 1; key <= 3; key++)
{
....
foreach (var item in tabItem)
{
item.ImagePath.Value = "images1/" + ("filename2_" + key);
item.ThumbPath.Value = "thumbnails1/" + ("filename2_" + key);
}
}
As stated above I need to convert ("filename2_" + key) into actual variable. Can anyone help me regarding this

You can't have dynamic variable names.
Variable names cannot be "created".
You can use an array or a generic collection to hold the collections of data you are using.
var fileSuffixList = new List<string>{ "xyz.jpg" , "abc.png", "qwe.jpg"};
foreach(string fileSuffix in fileSuffixList)
{
....
foreach (var item in tabItem)
{
item.ImagePath.Value = "images1/" + ("filename2_" + fileSuffix);
item.ThumbPath.Value = "thumbnails1/" + ("filename2_" + fileSuffix);
}
}

As #Oded stated, you can't have dynamic variable names.
What you can do is use a Collection such as a dictionary:
Dictionary<string, int> dictionary = new Dictionary<string, string>();
dictionary.Add("filename2_" + key, "Value");
If your keys are always numeric, you can also use an array or a List. However, without more information, it's hard to tell you the best way to go about it.

Related

Unable to find value by key in dictionary in case of comma separated key

I have a dictionary like below where i store list of file names with key generated as Csv1,Csv2 based on number of files.
I have a string array like below :
string[] files = { "SampleCSVFile_5300kb1.csv,SampleCSVFile_5300kb2.csv", "SampleCSVFile_5300kb3.csv"};
int counter=1;
var dictionary = new Dictionary<string, string>();
foreach (var file in files)
{
dictionary.Add("CSV" + counter, file);
counter++;
}
foreach (var file in files)
{
string myValue;
if (dictionary.TryGetValue(file, out myValue)) // getting null in out value
}
When i try to search for SampleCSVFile_5300kb1.csv i am getting null in my myValue variable.
Screenshot:
Update:i realize that i was adding wrong key so changed it like below but still unable to find CSV1 in case of SampleCSVFile_5300kb1.csv:
foreach (var file in files)
{
dictionary.Add(file,"CSV" + counter);
counter++;
}
Based on the comment you said in Amir Popoviches answer. I think you should alter your dictionary construction.
So you will create a mapping from each of the .csv file(s) to the "CSV1" etc string.
var files = new[] { "SampleCSVFile_5300kb1.csv,SampleCSVFile_5300kb2.csv", "SampleCSVFile_5300kb3.csv" };
var counter = 1;
var dictionary = new Dictionary<string, string>();
foreach (var file in files)
{
if (string.IsNullOrWhiteSpace(file))
{
continue;
}
foreach (var item in file.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries))
{
dictionary.Add(item, "CSV" + counter);
}
counter++;
}
And as you said in comments you want to find what "CSVX" file is for each of the files you have so we simulate you trying to find a match for these files. Notice that this array has all separate file names, in the upper array we had values comma separated so we group them together.
var files2 = new[] { "SampleCSVFile_5300kb1.csv", "SampleCSVFile_5300kb2.csv", "SampleCSVFile_5300kb3.csv" };
foreach (var file in files2)
{
string csvValue;
if (dictionary.TryGetValue(file, out csvValue))
{
Console.WriteLine("{0} -> {1}", file, csvValue);
}
}
This should output you
SampleCSVFile_5300kb1.csv -> CSV1
SampleCSVFile_5300kb2.csv -> CSV1
SampleCSVFile_5300kb3.csv -> CSV2
First argument in TryGetValue is key. So you should pass there "CSV" + counter to make it works.
https://msdn.microsoft.com/pl-pl/library/bb347013(v=vs.110).aspx
You are adding items to the dictionary with the following keys:
"CSV" + counter -> CSV1, CSV2...
And you are trying to find different values (e.g. "SampleCSVFile_5300kb1.csv,SampleCSVFile_5300kb2.csv") here:
foreach (var file in files)
{
string myValue;
if (dictionary.TryGetValue(file, out myValue)) // getting null in out value
}
Try below updated code:
string[] files = { "SampleCSVFile_5300kb1.csv,SampleCSVFile_5300kb2.csv", "SampleCSVFile_5300kb3.csv" };
int counter = 1;
var dictionary = new Dictionary<string, string>();
foreach (var file in files)
{
dictionary.Add("CSV" + counter, file);
counter++;
}
counter = 1;
foreach (var file in files)
{
string myValue;
//You need to pass key name here but you are passing value of it
//Need to update here
string keyName = "CSV" + counter;
if (dictionary.TryGetValue(keyName, out myValue)) ; // getting null in out value
counter++;
}
Iterate the dictionary an find your desired value using split by comma. you will get "SampleCSVFile_5300kb1.csv" and "SampleCSVFile_5300kb2.csv" into the fileName array for the same myvalKey
foreach (KeyValuePair<string, string> entry in dictionary)
{
string myvalKey = entry.Key;
string myval = entry.Value;
if (myval.Contains(',')) {
string[] fileNames = myval.Split(',');
}
}
From what I understand you seem to be looking for a way to match only part of a key. And while I suggest using the answers of Janne Matikainen and just add the parts of your key separately with the same value, regardless I will give you a way to match on a partial key using a bit of Linq.
string resultValue = null;
string resultKey = dictionary.Keys.FirstOrDefault(k => k.Contains(file));
if(resultKey != null)
resultValue = dictionary[resultKey];
this does assume only the first match is wanted, if you want all matching keys replace FirstOrDefault with Where.
Beware that while this code is easy it is not suitable for when performance is critical as you iterate over the keys basically using the dictionary as a
List<Tuple<string,string>>

Multiple Dictionaries in one MainDictionary c#

i hope you can give me a hint for my problem i have with my code.
I have a DataGridView which got its Data from an Excelfile.
Now to get structure in it, i want to make groups (keyword in dsdslls) and add valueNames (value of dsdslls and keyword in dslls) to that groups and add that content (value of dslls) to valueNames as KeyValuePair.
My Problem is not to add all that stuff, but to get it back.
here is the code (add stuff):
internal Dictionary<String, Dictionary<String, LinkedList<String>>> BuildList(DataGridView dgv)
{
//create the main Dictionary
Dictionary<String, Dictionary<String, LinkedList<String>>> dsdslls = new Dictionary<String, Dictionary<String, LinkedList<String>>>();
String groupName = "Project data", value = "", valueName = "", text = "";
//run through the whole list
for (int i = 0; i < dgv.RowCount - 1; i++)
{
//create new Dictionary for the Content
Dictionary<String, LinkedList<String>> dslls = new Dictionary<String, LinkedList<String>>();
//check if the String at i is a groupName, if so add it to groupName
if (isGroupName(dgv, i))
{
groupName = dgv.Rows[i].Cells[0].Value.ToString();
text = "Adding in group: " + groupName + " to value: ";
}
//now go forward in the list until you next Cell is empty or the list ended
do
{
//check if the String at i is a valueName, if so add it to valueName
if (isValueName(dgv, i))
{
//create the LinkedList for units and values
LinkedList<String> lls = new LinkedList<String>();
valueName = dgv.Rows[i].Cells[0].Value.ToString();
//check if group and valuename are NOT the same
if (isNotSame(valueName, groupName))
{
//now run the colums for units and values and add them to the List until you reach the end of used columns
int j = 0;
do
{
value = dgv.Rows[i].Cells[1 + j].Value.ToString();
lls.AddLast(value);
if (j == 0)
{
text += "\n" + valueName + " in (" + lls.First.Value.ToString() + "): ";
}
else
{
text += lls.Last.Value.ToString();
}
j++;
} while (j < dgv.Rows[i].Cells.Count - 1);
//add the valueName and List as new keyvaluepair to the dictionary.
dslls.Add(valueName, lls);
}
}
i++;
} while (!isStringEmpty(dgv.Rows[i].Cells[0].Value.ToString()) && i < dgv.RowCount - 1);
//show added content
MessageBox.Show(text);
//check if main dictionary contains the latest groupname, if not add the groupName and the last dictionary to the main dictionary
if (!dsdslls.ContainsKey(groupName))
{
dsdslls.Add(groupName, dslls);
}
}
MessageBox.Show("Building successfully finished.");
return dsdslls;
}
I'm not getting the right content back to the specified groupName... for example:" groupName = "Project Data" i got back the content of the group:" Electrical Network" which is the next keyword in the maindictionary
now the code to get the Data:
internal void /*Dictionary<String, LinkedList<String>>*/ GetGroupContent(Dictionary<String, Dictionary<String, LinkedList<String>>> dsdslls, String groupName)
{
//Dictionary<String, LinkedList<String>> dslls = new Dictionary<String, LinkedList<String>>();
String groupN = "", text = "";
//Check if Dictionary contains groupName
if (dsdslls.ContainsKey(groupName))
{
//run through the dictionary
foreach (var s in dsdslls)
{
//give back the keyword (just for the MessageBox)
if (s.Key == groupName)
{
groupN = s.Key;
}
else
{
//run throught the little dictionary to get the keywords from it.
foreach (var t in s.Value)
{
text += t.Key + "\n";
}
}
}
MessageBox.Show("Content of Group " + groupN + ": \n" + text);
text = "";
}
//return dslls;
}
Kind regards
Mirko
It is hard to understand what you expect from this code as the main problem is not well described.
Anyway, it seems that there might be problem in your data retrieval logic.
If you want to get data of group with matching name, then you have to move else part of your if statement. You need to do text concatenation only when group with correct name is found.
...
//give back the keyword (just for the MessageBox)
if (s.Key == groupName)
{
groupN = s.Key;
//run throught the little dictionary to get the keywords from it.
foreach (var t in s.Value)
{
text += t.Key + "\n";
}
}
...

How to build WebClient querystring with duplicate keys?

I'm posting data to a service that requires that I submit duplicate query string keys (ugly and not specified in any standards).
I'm using WebClient object to build the request. I'd like to keep using it since it is used frequently elsewhere in the project.
When I do this
foreach(var f in formats)
client.QueryString.Add("formats", f);
I get a list &formats=format_1,format_2,format_3 which the service does not support.
Is there a better alternative than this old-school ugliness:
var extraQueryString = string.Empty;
extraQueryString += "?apiKey=" + TRANSCODE_KEY;
extraQueryString += "&fileKey=" + fileKey;
foreach (var f in formats)
extraQueryString += "&formats=" + f;
var response = client.UploadData(TRANSCODE_URI + "task" + extraQueryString , new byte[] { });
The reason for this is because the NameValueCollection separates duplicate keys with commas. You could extend the NameValueCollection and override the Get method and have it return the format you want.
public class DupeNVC: NameValueCollection
{
private string _duplicateKey;
public DupeNVC(string duplicateKey = null)
{
_duplicateKey = duplicateKey;
}
public override string Get(int index)
{
//check if duplicate key has been specified
//if not, then call the default Get implementation
if (!String.IsNullOrEmpty(_duplicateKey))
{
ArrayList list = (ArrayList)base.BaseGet(index);
int num = (list != null) ? list.Count : 0;
if (num == 1)
{
return (string)list[0];
}
if (num > 1)
{
StringBuilder stringBuilder = new StringBuilder((string)list[0]);
for (int i = 1; i < num; i++)
{
//format our string and append the duplicate key specified
stringBuilder.AppendFormat("&{0}=", _duplicateKey);
stringBuilder.Append((string)list[i]);
}
return stringBuilder.ToString();
}
return null;
}
else
return base.Get(index);
}
}
You can use it like a normal NameValueCollection but if you pass in a duplicate strning in the constructor, it will look for that duplicate key and run the modified code above (otherwise it will just use the default base.Get method.
DupeNVC dnvc = new DupeNVC("formats");
foreach(var f in formats)
dnvc.Add("formats", f);
webClient.QueryString = dnvc;
This hasn't been fully tested but it should output the querystring format you want. Of course, this could be extended further by taking a collection of duplicate keys but this was just to give you an idea for your current problem.
Here's my take on this. WebClient essentially works like the ToString method of this class; it gets all the keys and then retrieves the values one at a time, doing a concatenate. So I override the AllKeys to return an array with repeated elements..
For example if a particular key has multiple values:
nvc["hello"] = { "a", "b", "c" }
Then my AllKeys will return an array with "hello" 3 times. WebClient will naively request it 3 times. A Dictionary tracks how many times a "hello" has been requested, and returns a different one each time (pseudo enumerator)
public class ParrotingNameValueCollection : NameValueCollection
{
Dictionary<string, int> _indexTracker = new Dictionary<string, int>();
public override string[] AllKeys
{
get
{
var l = new List<string>();
foreach (var k in base.AllKeys)
{
foreach (var x in (ArrayList)base.BaseGet(k))
l.Add(k);
_indexTracker[k] = 0;
}
return l.ToArray();
}
}
public override string Get(string name)
{
var list = (ArrayList)base.BaseGet(name);
var toReturn = (string)list[_indexTracker[name]];
_indexTracker[name]++;
return toReturn;
}
public override string ToString()
{
string delimiter = String.Empty;
StringBuilder values = new StringBuilder();
foreach (string name in this.AllKeys)
{
values.Append(delimiter);
values.Append((name));
values.Append("=");
values.Append((this[name]));
delimiter = "&";
}
return values.ToString();
}
}

C#: Nested dictionary issue

I have the code below which is intended to build a dictionary object with the following construction Dictionary<string<Dictionary<string, string>. For some reason each time I add an item to it the key text is correct but the value (dictionary) overwrites the previous one. This is probably better explained like this:
Iteration 1
key1, dictionary1
Iteration 2
key1, dictionary2
key2, dictionary2
Iteration 3
key1, dictionary3
key2, dictionary3
key3, dictionary3
What is causing this and how can I fix this code to stop it overwriting the dictionary in each entry?
QueryNameUserQueryString = new Dictionary<string, string>();
DialectDictionary = new Dictionary<string, Dictionary<string, string>>();
while (dataBaseConnection.NextRecord())
{
if (QueryNameUserQueryString != null)
{
QueryNameUserQueryString.Clear();
}
string dialect = dataBaseConnection.GetFieldById (0);
//If no dialect then carry out next iteration
if (String.IsNullOrEmpty (dialect))
{
continue;
}
try
{
dataBaseConnection2.ExecutePureSqlQuery ("SELECT * FROM " + sqlFactoryTable + " WHERE SQL_FACTORY_DIALECT = '" + dialect + "'");
}
catch
{
dataBaseConnection.Close();
dataBaseConnection2.Close();
throw;
}
//Do we have query strings for this dialect?
if (!dataBaseConnection2.HasRows())
{
continue;
}
//loop through query strings
while (dataBaseConnection2.NextRecord())
{
string queryName = dataBaseConnection2.GetFieldById (2);
string queryString = dataBaseConnection2.GetFieldById (3);
string user = dataBaseConnection2.GetFieldById (4);
//create composite key for dictionary
string compositeKey = dialect + "," + queryName + "," + user;
if (QueryNameUserQueryString != null)
{
//Construct our query string dictionary
QueryNameUserQueryString.Add (compositeKey, queryString);
}
}
//If we have a query string dictionary
if (QueryNameUserQueryString != null)
{
//Ensure m_dialect dictionary is not null
if (DialectDictionary != null)
{
//Construct our dictionary entry for this dialect
DialectDictionary.Add (dialect, QueryNameUserQueryString);
}
}
}
}
You seem to be using the same instance of QueryNameUserQueryString on every iteration. When it's added to the DialectDictionary, it's added as a reference - not a copy of the original.
To "properly" solve the issue, I would move the declaration of your QueryNameUserQueryString variable inside the while-scope. That way you would make sure that it can only exist in the scope of a single iteration, not across several. When it's added to the DialectDictionary, the reference lives on in that dictionary and you're safe to leave the scope.
You are using same instance of QueryNameUserQueryString everytime. Replace
QueryNameUserQueryString.Clear();
with
QueryNameUserQueryString = new Dictionary<string, string>();

Show values of List<string[]> without using extra variables or using the foreach loop

I have fallen into a doubt and I don't know how to solve it, the case is:
I have created an "arrayed string" list like this:
List<string[]> definitions;
I have added to it values like this:
definitions.Add(new string[2] { "A", "Def.1" });
definitions.Add(new string[2] { "B", "Def.2" });
In order to show the values I do it like this:
foreach (string[] theDefinition in definitions)
{
Console.WriteLine(theDefinition[0] + "\tdef: " + theDefinition[1]);
}
So far this works fine, but how can I show the values without the foreach I mean something like this:
Console.WriteLine(definitions[0] ...)
What should I write in the 3 dots to show either the "A" or the "Def.1" from the list in index 0.
I guess overcoming this is by doing something like:
string[] temp = definitions[0]
Console.WriteLine(temp[0] + ", " + temp[1]);
How to achieve it just using the Console.WriteLine without using extra variables, is this possible? and how? Thank you in advance.
Console.WriteLine(definitions[0][0] + "\tdef: " + definitions[0][1]);
The other answers are correct of course but why not just use a Dictionary instead of List of a 2 dimensional string array.
var definitions = new Dictionary<string, string>
{
{ "A", "Def.1" },
{ "B", "Def.2" }
};
foreach (var keypair in definitions)
{
Console.WriteLine("{0} \tdef: {1} ", keypair.Key, keypair.Value);
}
A better way would be to declare a definition type
public class Definition
{
public string Name { get; set; }
public string Value { get; set; }
public override string ToString()
{
return Name + "\tdef: " + Value;
}
}
Now you can simplify your code like this
List<Definition> definitions = new List<Definition> {
new Definition { Name = "A", Value = "Def.1" },
new Definition { Name = "B", Value = "Def.2" },
};
foreach (Definition theDefinition in definitions)
{
Console.WriteLine(theDefinition);
}
Of cause you can use a fluent version of it as proposed by Nikhil Agrawal, which is now even simpler.
definitions.ForEach(def => Console.WriteLine(def));
prints
A def: Def.1
B def: Def.2
And accessing the fields is more descriptive than using array indexes
Definition def = definitions[0];
Console.WriteLine(def.Name + ", " + def.Value);
// compared to
// Console.WriteLine(temp[0] + ", " + temp[1]);
You can access it like this: definitions[definition_index][string_index].
Try:
Console.WriteLine(definitions[0][0] + "\tdef: " + definitions[0][1]);
for (var i = 0; i < definitions.Length; i++)
{
Console.WriteLine(definitions[i][0] + "\tdef: " + definitions[i][1]);
}
One Line Answer instead of 3 Lines. No use of For or foreach Loop or Extra Variable when LINQ is here
definitions.ForEach(x => Console.WriteLine(x[0] + "\tdef: " + x[1]));

Categories

Resources