Here's what I've got, I need to keep the console from returning additional commas on the main program, so I probably need to rewrite string e. Month, description etc. should still have commas, but if something like "note" is absent, those additional commas would be gone.
public override string ToString()
{
string e = description + ", " + month + day + year + ", " + amount.ToString("C") + ", ";
e = e + paymentMethod + ", " + trip + ", " + note;
return e;
}
You can try something like this, to filter out empty elements:
public override string ToString()
{
string[] elements = new string[] { description,
String.Concat(month, day, year),
amount.ToString("C"), paymentMethod, trip, note };
return String.Join(", ", elements.Where(s => !String.IsNullOrWhiteSpace(s)));
}
A little more verbose option, but also less confusing and C# 2 compatible:
private static void AddIfNotNull(List<string> elements, string value)
{
if (!String.IsNullOrEmpty(value))
elements.Add(value);
}
public override string ToString()
{
List<string> elements = new List<string>();
AddIfNotNull(elements, description);
elements.Add(String.Concat(month, day, year));
elements.Add(amount.ToString("C"));
AddIfNotNull(elements, paymentMethod);
AddIfNotNull(elements, trip);
AddIfNotNull(elements, note);
return String.Join(", ", elements.ToArray());
}
You could rewrite ToString like this, is that what you want?
public override string ToString()
{
string e = description + " " + month + day + year + " " +
amount.ToString("C") + " ";
e = e + paymentMethod + " " + trip + " " + note;
return e;
}
Related
I've got a block of code which sums up time togged for various tasks in a project and returns the total hours logged per project (intMinutesLogged). How do I get my results n descending order?
static async void NotifyEntriesByWorkSpace(Dictionary<string, List<TimeEntry>> dicEntriesByWorkspace, string strChatURL)
{
string strMessage = "";
foreach (var kvpEntry in dicEntriesByWorkspace)
{
var lstTimeEntries = kvpEntry.Value;
string strTitle = "";
var intMinutesLogged = 0;
var intMinutesBillable = 0;
var intMinutesNonBillable = 0;
foreach (var objTimeEntry in lstTimeEntries)
{
if (objTimeEntry.Billable)
{
intMinutesBillable += objTimeEntry.TimeInMinutes;
}
else
{
intMinutesNonBillable += objTimeEntry.TimeInMinutes;
}
}
strTitle = Workspaces.getWorkspaceFromCache(kvpEntry.Key).Title;
//Console.WriteLine(intMinutesLogged + ": " + strTitle + "m");
intMinutesLogged = intMinutesBillable + intMinutesNonBillable;
Console.WriteLine(TimeLoggedMessage(intMinutesLogged) + ": " + strTitle + " " + "(Billable: " + TimeLoggedMessage(intMinutesBillable) + ";" + " " + "Non-Billable: " + TimeLoggedMessage(intMinutesNonBillable) + ")");
strMessage += TimeLoggedMessage(intMinutesLogged) + ": " + strTitle + " " + "(Billable: " + TimeLoggedMessage(intMinutesBillable) + ";" + " " + "Non-Billable: " + TimeLoggedMessage(intMinutesNonBillable) + ")" + "\n";
}
await SendMessage(strChatURL, strMessage);
}
static string TimeLoggedMessage(int intMinutesLogged)
{
return intMinutesLogged / 60 + "h" + " " + intMinutesLogged % 60 + "m";
}
You could use LINQ for this: https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.orderbydescending?view=net-6.0
You could create a simple class or anonymous type to hold the integer values you're summing up (total minutes, billable minutes, non-billable minutes). Then you could populate a collection of this type within the code you shared and afterwards call OrderByDescending on it. You could order based on any of the three integer values.
I have the following statement
xdoc.Descendants("Father").Select(p => new
{
Son1 = (string)p.Element("Son1").Value,
Son2 = (string)p.Element("Son2").Value,
Son3= (string)p.Element("Son3").Value,
Son4 = (string)p.Element("Son4").Value,
Son5 = (string)p.Element("Son5").Value
}).ToList().ForEach(p =>
{
Response.Write("Son1= " + p.Son1 + " ");
Response.Write("Son2=" + p.Son2 + " ");
Response.Write("Son3=" + p.Son3 + " ");
Response.Write(("Son4 =") + p.Son4 + " ");
Response.Write(("Son5 =") + p.Son5 + " ");
Response.Write("<br />");
});
and it works fine as long as i have only one instance of each son , the problem is that i have multiple instances of Son5, and i don´t know how to put Son5 inside of a list
Here is my XML code Example:
If you have several elements of same type, then you should parse them to list or other collection:
var fathers = from f in xdoc.Descendants("Father")
select new {
Son1 = (string)f.Element("Son1"),
Son2 = (string)f.Element("Son2"),
Son3= (string)f.Element("Son3"),
Son4 = (string)f.Element("Son4"),
Son5 = f.Elements("Son5").Select(s5 => (string)s5).ToList()
};
Some notes:
Don't use .Value of XElement or XAttribute - you can cast element itself to appropriate data type without accessing its value. Benefits - less code, more reliable in case element is missing (you will not get NullReferenceException)
Consider to use int or int? as elemenent values if your elements contain integer values
If you have single Father element, then don't work with collection of fathers. Just get xml root and check whether it's null or not. After that you can create single father object.
Writing response
foreach(var father in fathers)
{
Response.Write($"Son1={father.Son1} ");
Response.Write($"Son2={father.Son2} ");
Response.Write($"Son3={father.Son3} ");
Response.Write($"Son4={father.Son4} ");
Response.Write(String.Join(" ", father.Son5.Select(son5 => $"Son5={son5}"));
Response.Write("<br />");
}
Try this:
xdoc.Descendants("Father").Select(p => new
{
Son1 = p.Element("Son1").Value,
Son2 = p.Element("Son2").Value,
Son3= p.Element("Son3").Value,
Son4 = p.Element("Son4").Value,
Sons5 = p.Elements("Son5").Select(element => element.Value).ToList()
}).ToList().ForEach(p =>
{
Response.Write("Son1= " + p.Son1 + " ");
Response.Write("Son2=" + p.Son2 + " ");
Response.Write("Son3=" + p.Son3 + " ");
Response.Write("Son4 =" + p.Son4 + " ");
p.Sons5.ForEach(son5 => Response.Write("Son5 =" + son5 + " "));
Response.Write("<br />");
});
That will create a list of Son5 within your list of items, which you can iterate in the ForEach with another ForEach.
private void btnAssemble_Click(object sender, EventArgs e)
{
txtAssembled.Text = (cboTitle.Text + txtFirstName.Text[0] + txtMiddle.Text + txtLastName.Text + "\r\n" +txtStreet.Text + "\r\n"+ cboCity.Text);
}
I'm trying to get 1 character white space inbetween cboTitle.Text, txtFirname.Text, txtMiddle.Text, and txtLastName, but they all output the information together, but I want them spaced evenly. what do I need to do? thanks in advance.
I'm going to post some other code thats below the one above in my project, just in case it might be relevant.
string AssembleText(string Title, string FirstName, string MiddleInitial, string LastName, string AddressLines, string City )
{
string Result = "";
Result += Title + " ";
Result += FirstName.Substring(0, 2) + " ";
// Only append middle initial if it is entered
if (MiddleInitial != "")
{
Result += MiddleInitial + " ";
}
Result += LastName + "\r\n";
// Only append items from the multiline address box
// if they are entered
if ( AddressLines != "")
{
Result += AddressLines + "\r\n";
}
//if (AddressLines.Length > 0 && AddressLines.ToString() != "")
//{
// Result += AddressLines + "\r\n";
//}
Result += City;
return Result;
}
}
}
If you just want a space between those specific fields in btnAssemble_Click, you can just insert them like this:
string myStr = foo + " " + bar + " " + baz;
So your first function would be modified to read:
private void btnAssemble_Click(object sender, EventArgs e)
{
txtAssembled.Text = (cboTitle.Text + " " + txtFirstName.Text[0] + " " + txtMiddle.Text + " " + txtLastName.Text + "\r\n" + txtStreet.Text + "\r\n" + cboCity.Text);
}
A few other comments:
It's not clear to me what the AssembleText() function you posted has to do with this. I am confused though, as I see a few lines appending spaces at the end just like I mentioned above.
Using the String.Format() function may make this code easier to read and maintain.
Using Environment.NewLine instead of "\r\n" will make the string contain the newline character defined for that specific environment.
Using a StringBuilder object may be faster over concatenation when building strings inside of a loop (which may not apply here).
Using String.format() should feet the bill. It also make your code easy to read.
txt.assembled.text = String.Format("{0} {1} {2} {3}",
cboTitle.Text,
txtFirstName.Text[0],
txtMiddle.Text,
txtLastName.Text
);
It would be like this
private void btnAssemble_Click(object sender, EventArgs e)
{
txtAssembled.Text = (cboTitle.Text + " " + txtFirstName.Text[0] + " " +txtMiddle.Text + " " + txtLastName.Text + "\r\n" +txtStreet.Text + "\r\n"+ cboCity.Text);
}
It seems that you want String.Join; whenever you want to combine strings with a delimiter, say, " " (space) all you need is to put
String combined = String.Join(" ",
cboTitle.Text,
txtFirstName.Text[0],
txtMiddle.Text,
txtLastName.Text);
Complete implementation (joining by space and new line) could be
txtAssembled.Text = String.Join(Environment.NewLine,
String.Join(" ",
cboTitle.Text,
txtFirstName.Text[0],
txtMiddle.Text,
txtLastName.Text),
txtStreet.Text,
cboCity.Text);
Here is the offending code. I haven't done much string manipulation yet, and am currently having issues.
if (orderid != orderlist[orderlist.Count - 1])
{
response2 = GetSubstringByString("{\"orderid\": \"" + orderid + "\"", "{\"orderid\": \"", response2);
}
else
{
response2 = GetSubstringByString("{\"orderid\": \"" + orderid + "\"", "success", response2);
}
Console.WriteLine("Response 2 is: " + response2);
logger.Log("Writing " + writepath + filename);
File.WriteAllText(writepath + filename, response2);
}
public string GetSubstringByString(string a, string b, string c) //trims beginning and ending of string
{
Console.WriteLine("String a is: " + a + "String b is: " + b + "String c is: " + c);
return c.Substring((c.IndexOf(a) + a.Length), (c.IndexOf(b) - c.IndexOf(a) - a.Length));
}
I am having issues extracting a substring, as the beginning and ending strings are the same, and therefore it is unable to differentiate the strings from each other.
Here is the main issue:
response2 = GetSubstringByString("{\"orderid\": \"" + orderid + "\"", "{\"orderid\": \"", response2);
Is there a way I can add a check if the orderid for the ending string differs from the starting string orderid? Thanks for any help!
I was working with code that was already set to scan rather than parse JSON in the optimal fashion.
I utilized this regex to remove orderid before each number as to not cause scanner length exceptions. I also overloaded string.IndexOf as mentioned by juharr.
var regex = new Regex(Regex.Escape("orderid")); //replace first occurrence of orderid
response2 = regex.Replace(response2, "", parsecount-1);
public string GetSubstringByString(string a, string b, string c) //trims beginning and ending of string
{
logger.Log("String a is: " + a + "String b is: " + b + "String c is: " + c);
var offset = c.IndexOf(b);
//lastcheck will return 0 if it's last element in orderlist, because ending string differs for last
return c.Substring((c.IndexOf(a) + a.Length), (c.IndexOf(b, offset + lastcheck) - c.IndexOf(a) - a.Length));
}
I have method in C#, I have to return all values from ArrayList.
public string vyhledavaniOS()
{
foreach (Vozidlo voz in nabídka)
{
if (voz is OsobníVůz)
return (voz.TypVozidla() + ": SPZ: " + voz.JakaSPZ + ", Značka: " + voz.JakaZnacka + ", Barva: " + voz.JakaBarva);
}
}
This code returns only one value, is there any way, how to return all values?
Yes, you need to change the method to return an array of strings instead of only one string value. Something like this:
public List<string> vyhledavaniOS()
{
List<string> listToReturn = new List<string>();
foreach (Vozidlo voz in nabídka)
{
if (voz is OsobníVuz)
listToReturn.Add((voz.TypVozidla() + ": SPZ: " + voz.JakaSPZ + ", Znacka: " + voz.JakaZnacka + ", Barva: " + voz.JakaBarva));
}
return listToReturn;
}