Problem adding to dictionary in c# - c#

Alright so I've looked hard but I couldn't seem to find answer to my problem. There must be a problem in my code and it would be really helpful if someone could look at it for me.
Dictionary<string, string> keylist = new Dictionary<string, string>();
if (intext.Contains("addkey") && intext.Contains("def"))
{
string[] keywords = intext.Split(' ');
string key1 = keywords[1];
string def2 = keywords[3];
string fkey = key1.Replace("_", " ");
string fdef = def2.Replace("_", " ");
keylist.Add(fkey, fdef);
say("Phrase '" + fkey + "' added with response '" + fdef + "'");
say("Your Dictionary contains " + keylist.Count.ToString() + " word(s).");
//////////////////////////////
}
All I want it to do is take the input in the form of "addkey key_here def definition_here" and add it to the dictionary. I added the counting part for debugging purposes and it always says I only have 1 word in the dictionary no matter how many I have added. You can probably tell I'm new so please be gentle. Thanks

Dictionary<string, string> keylist = new Dictionary<string, string>();
I'm assuming that this function is called whenever the user enters some sort of command (e.g. from the command line, when they click a button, etc.). If this is the case, you need to have your keylist dictionary at a higher level (as an instance variable, for example). The way the code is now, every time the function is called a new dictionary is created and the key is added to it; this is why there's only one.
At the risk of misjudging or oversimplifying your problem, just moving the line I quoted above outside of the function body should help.

In the code as given you are recreating the dictionary every time you run it.
Dictionary<string, string> keylist = new Dictionary<string, string>();
Reinitializes the variable keylist to an empty dictionary.
Instead try moving that line outside of the function. Since you are using winforms, you can create a class level variable, something like this:
public partial class Form1 : Form
{
Dictionary<string, string> keylist = new Dictionary<string, string>();
public Form1()
{
InitializeComponent();
}
public void YourFunction(string intext)
{
if (intext.Contains("addkey") && intext.Contains("def"))
{
string[] keywords = intext.Split(' ');
string key1 = keywords[1];
string def2 = keywords[3];
string fkey = key1.Replace("_", " ");
string fdef = def2.Replace("_", " ");
keylist.Add(fkey, fdef);
say("Phrase '" + fkey + "' added with response '" + fdef + "'");
say("Your Dictionary contains " + keylist.Count.ToString() + " word(s).");
}
}
}

You need to loop through the if (intext.Contains...{} block or it only runs once. If you are looping through it and only getting one entry in the Dictionary, it's because you keep reassigning it within the scope in a scenario such as:
while(true) {
Dictionary<string, string> keylist = new Dictionary<string,string>();
//...
}
So you'll need to move it outside, if that's your case.

I'm not sure exactly what your input string is or how you need to use it, though I think you're looking to split the input string and loop through along this line...
private Dictionary<string, string> GetData(string intext)
{
Dictionary<string, string> keylist = new Dictionary<string, string>();
string[] keywords = intext.Split(' ');
foreach (string s in keywords)
{
if (s.Contains("addkey") && s.Contains("def"))
{
string fkey = key1.Replace("_", " ");
string fdef = def2.Replace("_", " ");
keylist.Add(fkey, fdef);
say("Phrase '" + fkey + "' added with response '" + fdef + "'");
say("Your Dictionary contains " + keylist.Count.ToString() + " word(s).");
}
}
return keylist;
}

Related

how to pass an additional parameter to an OnClick event, asp.net web form?

I have a function called "CreateReportForEachCompany" as following:
protected Dictionary<int, List<ReportObject>> CreateReportForEachCompany()
{
try
{
Dictionary<int, List<ReportObject>> dict = new Dictionary<int, List<ReportObject>>();
EnvironmentVariable.setEnvId((int)environmentEnum.mll);
//bakashot_tarif is a VIEW not a TABLE
DataTable dt = GeneralDbExecuterService.executeSqlSelectDataScript("select * from bakashot_tarif");
foreach (DataRow dr in dt.Rows)
{
var reportRow = FillObjectWithValues(dr);
int company_Id = dr.Field<int>("company_Id");
CreateDictionaryPairIfNotExist(dict, company_Id);
dict[company_Id].Add(reportRow);
}
return dict;
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
now lets say I invoked it that way and got myself a dictionary with keys/values as needed.
var dictionary = CreateReportForEachCompany();
now.. I have another function named:
CreateCsvForEachCompany(Dictionary<int, List<ReportObject>> dict)
that TAKES the dictionary as parameter and creates few csvs based on the dictionary keys..
now those two functions above are executed on button click as following:
protected void ExecuteProgram(object sender, EventArgs e)
{
var dictionary = CreateReportForEachCompany();
CreateCsvForEachCompany(dictionary);
}
after that, I have a function named TransferSftpOnClick which meant to transfer file via SFTP (secure file transfer protocol ) into a designated location in the server:
void TransferSftpOnClick(Dictionary<int, List<ReportObject>> dict)
{
EnvironmentVariable.SetSubject(EnvironmentVariable.appSubjectEnum.btl);
string systemId = "MLL";
string fileType = "HIYUV-CHEVRA";
string chargeMonth = DateTime.Now.ToString("yyyyMM");
var fileCreationDate = DateTime.Now.ToString("yyyyMMdd");
string fileCreationTime = DateTime.Now.ToString("HHmmss");
string subject = EnvironmentVariable.appSubjectEnum.btl.ToString().ToUpper();
string location = EnvironmentVariable.getLocalFilePath() + #"\";
foreach (KeyValuePair<int, List<ReportObject>> entry in dict)
{
FtpUtil ftp = new FtpUtil();
int key = entry.Key;
string fileName = systemId + "-" + fileType + "-" + String.Format("{0:00000}", key) + "-" + chargeMonth + "-" + fileCreationDate + "-" + fileCreationTime + ".CSV";
**ftp.saveFileToFtp(location, key.ToString(), fileName, subject);**
}
}
I want my function to recognize the dictionary that is executed in function "ExecuteProgram()"
And I want to trigger onClick on TransferSftpOnClick that will just transfer me the files to the designated location.
how can I achieve that? is it even worth doing?
or should I just do this:
FtpUtil ftp = new FtpUtil();
ftp.saveFileToFtp(location, key.ToString(), fileName, subject);
under the CreateCsvPerCompany to avoid that mess?
hope I was clear, thanks

Create string with action name and all user inputs

We are reviewing our logs to make it more effective for audit analysis, therefore we are trying to include the action name and all inputs applied each time by the user.
Consider this sample code:
public JsonResult SampleActionCode(int inputA, Guid inputB, bool inputC)
{ ... }
So our code would be something similar to this added at that action:
string actionName = this.ControllerContext.RouteData.Values["action"].ToString();
string userInputs = inputA.ToString() + " , " + inputB.ToString() + " , " + inputC.ToString();
string userExecuted = actionName + " , " + userInputs;
//save to database
How could we make a general code that would cycle all inputs available and concatenate those into a string, similar to userInputs shown?
The query is stored in Request.QueryString, so you can iterate over its parts:
var parts = new List<string>(); // using System.Collections.Generic
foreach (var key in Request.QueryString.AllKeys) {
parts.Add(Request.QueryString[key]);
}
string result = string.Join(", ", parts);

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.

Changing text in a .txt file using c#

Basically im trying to save a new password and avatar for my twitter type website.
Any help would be appreciated
My coding is:
string newPasswordString = Server.MapPath("~") + "/App_Data/tuitterUsers.txt";
string[] newPasswordArray = File.ReadAllLines(newPasswordString);
string newString = Server.MapPath("~") + "/App_Data/tuitterUsers.txt";
newString = File.ReadAllText(newString);
string[] newArray = newString.Split(' ');
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; i++)
{
newArray[1] = newPasswordTextBox.Text;
newArray[2] = avatarDropDownList.SelectedValue;
newPasswordArray.Replace(" " + Session["Username"].ToString() + " " + Session["UserPassword"].ToString() + " " + Session["UserAvatarID"].ToString() + " ", " " + Session["Username"].ToString() + " " + newPasswordArray[1] + " " + newPasswordArray[2]);
}
}
string newPasswordString = string.Join(Environment.NewLine, newPasswordArray);
File.WriteAllText(Server.MapPath("~") + "/App_Data/tuitterUsers.txt", newPasswordString);
If I understand your problem correctly you need to move the
File.WriteAllText(Server.MapPath("~") + "/App_Data/tuitterUsers.txt", newPasswordArray);
outside the loop, otherwise you rewrite the file at each loop, but this is not enough, you need also to rebuild the Whole text file
string fileToWrite = string.Join(Environment.NewLine, newPasswordArray);
File.WriteAllText(Server.MapPath("~") + "/App_Data/tuitterUsers.txt", fileToWrite);
EDIT: After the code update and the comment below
The looping is totally wrong as well the rebuilding of the array
string userDataFile = Server.MapPath("~") + "/App_Data/tuitterUsers.txt";
string[] userDataArray = File.ReadAllLines(userDataFile);
for(int x = 0; x < userDataArray.Length; x++)
{
string[] info = userData[x].Split(' ');
if(Session["Username"].ToString() == info[0])
{
userData[x] = string.Join(" ", Session["UserName"].ToString(),
newPasswordTextBox.Text,
avatarDropDownList.SelectedValue.ToString());
break;
}
}
string fileToWrite = string.Join(Environment.NewLine, userDataArray);
File.WriteAllText(Server.MapPath("~") + "/App_Data/tuitterUsers.txt", fileToWrite);
Keep in mind that this works for a limited number of users.
If you are lucky and you site becomes the new Twitter, you cannot think to use a solution where you read in memory the names of all your users.
Firstly, what you're doing is A Bad Idea™. Given that a web server can have multiple threads in operation, you can't be certain that two threads aren't going to be writing different data at the same time. The more users you have the larger your user file will be, which means it takes longer to read and write the data, which makes it more likely that two threads will come into conflict.
This is why we use databases for things like this. Instead of operating on the whole file every time you want to read or write, you operate on a single record. There are plenty of other reasons to do it to.
That said, if you insist on using a text file...
If you treat each line in the file as a record - a single user's details in this case - then it makes sense to build a class to handle the content of those records, and make that class able to read and write the line format.
Something like this:
class UserRecord
{
public string Name;
public string Password;
public string Avatar;
public UserRecord(string name, string password, string avatar)
{
Name = name;
Password = password;
Avatar = avatar;
}
// static factory method
public static UserRecord Parse(string source)
{
if (string.IsNullOrEmpty(source))
return null;
string[] parts = source.Split(',');
if (parts.Length < 3)
return null;
return new UserRecord(parts[0], parts[1], parts[2]);
}
// convert to string
public string ToString()
{
return (new string[] { Name, Password, Avatar }).Join(",");
}
}
Adjust the Parse method to handle whatever format you're using for the data in the line, and change the ToString method to produce that format.
Once you have that working, use it to parse the contents of your file like this:
// Somewhere to put the data - a Dictionary is my first choice here
Dictionary<string, UserRecord> users = new Dictionary<string, UserRecord>();
// Don't forget to use 'using' where appropriate
using (TextReader userfile = File.OpenText(userDataFile))
{
string srcline;
while ((srcline = userfile.ReadLine()) != null)
{
UserRecord user = UserRecord.Parse(line);
if (user != null)
users[user.Name] = user;
}
}
Then you can access the user's data by username, manipulate it as required, and save it back out whenever you like.
Writing the data back out from a Dictionary of users is as simple as:
StringBuilder sb = new StringBuilder;
foreach (UserRecord user in users.Values)
{
sb.AppendFormat("{0}\n", user);
}
File.WriteAllText(userDataFile, sb.ToString());
Meanwhile, you have a users collection that you can save for future checks and manipulations.
I still think you should use a database though. They're not hard to learn and they are far better for this sort of thing.

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];
}

Categories