How can I successfully extract this substring in C#? - c#

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

Related

Results in descending order

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.

How to Convert and Reverse MAC Address to Bytes C#

I need to convert an MAc Address - 88:E9:FE:A8:1F:2F
for this format '0xA8FEE988 0x00002F1F 0x00000000 0x00000000'
I did this code below, but it is not elegant. Someone can help me?
string txtMacAddr = "88:E9:FE:A8:1F:2F";
string cmdMAc = "";
var macReverso = Util.Mac_Reverso(txtMacAddr.Replace(":",""));
string[] macRev = new string[4];
macRev[0] = $"0x{macReverso.Substring(4, 8)}";
macRev[1] = $"0x0000{macReverso.Substring(0, 4)}";
macRev[2] = "0x00000000";
macRev[3] = "0x00000000";
foreach (var xl in macRev)
{
cmdMAc += xl + " ";
}
Logger.WriteLine(cmdMAc); //op '0xA8FEE988 0x00002F1F 0x00000000 0x00000000'
public static string Mac_Reverso(string macAddress)
{
string macRevertido = string.Empty;
string s = macAddress.Replace("0x", "");//'0xA8FEE988 0x00002F1F 0x00000000 0x00000000'
string[] macLista = s.Split(' ');
foreach (var mac in macLista)
{
for (var i = mac.Length; i > 0; i -= 2)
{
macRevertido += mac.Substring(i - 2, 2);
if (macRevertido.Length == 12)
{
return macRevertido; //2F1FA8FEE988
}
}
}
return macRevertido;
}
What do you mean by not elegant? The following code will get the same result and in my opinion its easier to read. The first option is to show it can be done just by using char references, if the mac address will always look the same. The second result is easier to read in my head.
Note: If 88 was changed to 08 and the zero was omitted for some reason, the the following input would break both of them: 8:E9:FE:A8:1F:2F Does this case matter to you?
Is the output you included in your post what you are trying to get? What exactly are you trying to do?
//Reference each char individually. Could break if char position changes.
string mac = "88:E9:FE:A8:1F:2F";
string reverseMac = "0x" + mac[9] + mac[10] + mac[6] + mac[7] + mac[3] + mac[4] + mac[0] + mac[1] + " 0x0000" + mac[15] + mac[16] + mac[12] + mac[13] + " 0x00000000 0x00000000";
//Output:0xA8FEE988 0x00002F1F 0x00000000 0x00000000
//Better Option: Split by the ':' delimiter and reference each group of chars.
string[] macChars = mac.Split(":"); //Breaks into groups
string newMac2 = "0x" + macChars[3] + macChars[2] + macChars[1] + macChars[0] + " 0x0000" + macChars[5] + macChars[4] + " 0x00000000 0x00000000";
//Output: 0xA8FEE988 0x00002F1F 0x00000000 0x00000000
Update: Based on what you are trying to do, two methods would be better. You could reuse your Mac_Reverso in place of RevertMac below.
//Input 88:E9:FE:A8:1F:2F
//Output 0xA8FEE988 0x00002F1F 0x00000000 0x00000000
public static string ConvertMac(string macAddress)
{
string[] macChars = macAddress.Split(":");
string macRevertido = "0x" + macChars[3] + macChars[2] + macChars[1] + macChars[0] + " 0x0000" + macChars[5] + macChars[4] + " 0x00000000 0x00000000";
return macRevertido;
}
//Input 0xA8FEE988 0x00002F1F 0x00000000 0x00000000
//Output 88:E9:FE:A8:1F:2F
public static string RevertMac(string mc)
{
string revertedMac = "" + mc[8] + mc[9] + ":" + mc[6] + mc[7] + ":" + mc[4] + mc[5] + ":" + mc[2] + mc[3] + ":" + mc[19] + mc[20] + ":" + mc[17] + mc[18];
return revertedMac;
}
This doesn't address the endian issues Neil mentioned. Your question mentions reversing bytes, and your output format implies reversing the order of bytes in the array. Is that your objective?

Add pause to Alexa without using SSML

Is there a way to add a pause (preferably 1 second) in Amazon Alexa without using SSML? Perhaps there is a trick I can do with the Outputspeech.Text and I just don't know it.
Below, I am saying "Here are works of art by {artist name}" but the name and the start of the works of art become mixed together - in spite of the period - so I end up with things like "Here are the works of art by Pablo Picasso Harlequin..."
I am using C# and my own https endpoint, not AWS Lambda.
Any suggestions? Otherwise I will add it as SSML. Thanks.
var output = new StringBuilder();
var outputCard = new StringBuilder();
string m_location;
string m_current_location;
string m_artist = dt_artist.Rows[0]["DisplayName"].ToString();
output.Append("here are works of art for " + m_artist + ". ");
outputCard.Append("Here are works of art for " + m_artist + ".\n\n");
foreach (DataRow dr in dt_artist_objs.Rows)
{
m_current_location = dr["CurrentLocation"].ToString();
if (m_current_location == " ")
{
m_location = "The location is not available.";
}
else
{
m_location = "It is located on the " + m_current_location;
}
output.Append(dr["Title"].ToString() + " is a " + dr["Classification"].ToString() + ". The medium is " + dr["Medium"].ToString() + ". " + m_location);
outputCard.Append(dr["Title"].ToString() + ", " + dr["Dated"].ToString() + " is a " + dr["Classification"].ToString() + ". The medium is " + dr["Medium"].ToString() + ". " + dr["Creditline"].ToString() + ". " + m_location + ".\n"); // It is located on the " + dr["CurrentLocation"].ToString());
}
sql_conn_data.Close();
response.Response.OutputSpeech.Text = output.ToString();
response.Response.Card.Title = "Art";
response.Response.Card.Type = "Standard";
response.Response.Card.Text = outputCard.ToString();
response.Response.ShouldEndSession = true;
return response;
UPDATE
OK. Ended up going the SSML route which looks like this:
var output = new StringBuilder();
var outputCard = new StringBuilder();
string m_location;
string m_current_location;
string m_location_card;
string m_artist = dt_artist.Rows[0]["DisplayName"].ToString();
output.Append("<speak>");
output.Append("here are works of art for " + m_artist + ". <break time='1s'/> ");
outputCard.Append("Here are works of art for " + m_artist + ".\n\n");
foreach (DataRow dr in dt_artist_objs.Rows)
{
m_current_location = dr["CurrentLocation"].ToString();
if (m_current_location == " ")
{
m_location = "The location is not available. <break time='1s' />";
m_location_card = "The location is not available. ";
}
else
{
m_location = "It is located on the " + m_current_location + "<break time = '1s' />";
m_location_card = "It is located on the " + m_current_location;
}
output.Append(dr["Title"].ToString() + " is a " + dr["Classification"].ToString() + ". The medium is " + dr["Medium"].ToString() + ". " + m_location);
outputCard.Append(dr["Title"].ToString() + ", " + dr["Dated"].ToString() + " is a " + dr["Classification"].ToString() + ". The medium is " + dr["Medium"].ToString() + ". " + dr["Creditline"].ToString() + ". " + m_location_card + ". \n");
}
output.Append("</speak>");
sql_conn_data.Close();
response.Response.OutputSpeech.Ssml = output.ToString();
response.Response.OutputSpeech.Type = "SSML";
response.Response.Card.Title = "Art";
response.Response.Card.Type = "Standard";
response.Response.Card.Text = outputCard.ToString();
response.Response.ShouldEndSession = true;
return response;
}
There is not a way to introduce a pause in Alexa without SSML. You will need to build the ssml string and return it back to Alexa using the pause, or the cadence strings.

C# Creating white space lines between assembled .text

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);

Removing extra commas from C# constructor

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

Categories