I'm trying to get some part of string by substring and this is my string :{"samanState":"OK","samanResNum":"97d590e2-9ce3-49f9-85cf-2228b33cad57","samanTraceNo":"479936"} I can't do something like this : substring(8,16) because this string is change every time. I want to get 479936 from that. I'm sure TraceNo":" is static and never change so I did this :
<td>#(bankDepositHistoryItem.AdditionalData.Substring
(bankDepositHistoryItem.AdditionalData.IndexOf("TraceNo\":\""),
bankDepositHistoryItem.AdditionalData.Length- bankDepositHistoryItem.AdditionalData.IndexOf("TraceNo\":\"")-2)) </td>
but the out put is : TraceNo":"479936 How should I get this : 479936
I have to say that I Know this is possible with serialize and deserialize but I want to know if this is possible with substring or split or methods like these.
Many thanks
That is a JSON string, so I would first convert the string to a .NET object using the popular Json.NET framework library.
After adding the Newtonsoft.Json NuGet package to your project, your code would look something like this:
#using Newtonsoft.Json.Linq //add this to your Razor page or to _ViewImports.cshtml
<td>#(JObject.Parse(bankDepositHistoryItem)["samanTraceNo"])</td>
If you still want to parse the string, you can use a couple of handy string extension methods (I have variations for integers and Regex as well):
public static string Past(this string s, string starter) {
var starterPos = s.IndexOf(starter);
return starterPos == -1 ? String.Empty : s.Substring(starterPos + starter.Length);
}
public static string UpTo(this string s, string stopper) {
var stopPos = s.IndexOf(stopper);
return (stopPos >= 0) ? s.Substring(0, stopPos) : s;
}
Then extract with:
var ans = bankDepositHistoryItem.Past("\"samanTraceNo\":\"").UpTo("\"");
Related
I'm using Spectre.Console and have plenty of AnsiConsole.MarkupLine commands like this:
AnsiConsole.MarkupLine($"[lime]File size:[/] [bold]\t{file.Length,-10}[/]");
I'd like to output the same text in plaintext with no color in a text file, like
var msg = $"[lime]File size:[/] [bold]\t{file.Length,-10}[/]"
AnsiConsole.MarkupLine(msg);
var msgclean = AnsiConsole.StripTag(msg);
LogToFile(msgclean);
Is there a way to strip the tags? Or redirect the console output some way to a file?
I dug through their API and found this extension method that should do the trick : RemoveMarkup() https://spectreconsole.net/api/spectre.console/stringextensions/29bfb33e
See if the following language extension will work for you. Regex pattern taken from this post. Try via dotnetfiddle.
public static class StringExtensions
{
private static readonly Regex Whitespace = new(#"\s+");
public static string Flatten(this string value)
=> value is null or "" ?
value :
Whitespace.Replace(value.Trim(), " ");
public static string StripCodes(this string sender)
=> Regex.Replace(sender, #"\[[^]]*\]", "")
.Flatten();
}
I have a string that could be anything like
100100001
or
101000
I need to find a way to remove the 100 until it's reduced to it's simplest form
100100001 ==> 001
101000 ==> empty
Can't use 3rd party tools
must only use
System
System.Collections.Generic
System.IO
You can do it with a simple loop, checking if the string contains the value an if it does, replace it with blank:
var input = "101000";
while(input.Contains("100"))
{
input = input.Replace("100", "");
}
You could also use recursion, something like this:
public string Reduce(string s)
{
return s.Contains("100") ? Reduce(s.Replace("100", string.Empty)) : s;
}
The object has 139 fields; the string initializer may have some or all of these fields. It is formatted like this: "FirstName":"Bart","LastName":"Simpson","Company":"Fat Tony's","Address":"55 Maple Drive" etc. I could just look for the fields like this:
if (initializerString.contains("FirstName:")
FirstName="get the next series of chars until the ", or end of string
and so forth. But is there a more compact way to do this?
Seeing as your format is incredibly similar to JSON (except for the lack of braces, actually), as people commented you'll fare better by using JSON.NET.
If you have complete control over this string, just transform it into a json and deserialize it:
JsonConvert.DeserializeObject<YourClass>(yourString);
It will automatically set the correct properties while deserializing your data.
In case you don't have control of this format, and you need to parse it anyway, just put up the braces and you're good:
JsonConvert.DeserializeObject<YourClass>("{" + yourString + "}");
And if you don't have a specific class for this, you can also replace YourClass for a Dictionary<string,object>
You'll find this library as Newtonsoft.Json, and I believe it's the most popular library for dealing with JSON data.
I've made a working example so you can see it in action (note that I kept your string format, but please try to use straight json):
using System;
using System.Linq;
using System.Collections.Generic;
using Newtonsoft.Json;
public class Program
{
public class Information
{
public string FirstName{get;set;}
public string LastName{get;set;}
public string Company{get;set;}
public string Address{get;set;}
}
public static void Main()
{
string myObject = "\"FirstName\":\"Bart\",\"LastName\":\"Simpson\",\"Company\":\"Fat Tony's\",\"Address\":\"55 Maple Drive\"";
var converted = JsonConvert.DeserializeObject<Dictionary<string, object>>("{"+myObject+"}");
var converted2 = JsonConvert.DeserializeObject<Information>("{"+myObject+"}");
Console.WriteLine(String.Join("\n", converted.Select(c=> c.Key + ": " + c.Value)));
Console.WriteLine(converted2.FirstName);
}
}
And here's a bonus fiddle:
https://dotnetfiddle.net/fudUYZ
Using regex you could do:
string firstName = Regex.Match(yourstring,#"(?<=""FirstName"":"").*?(?="")").Value;
However this really looks like a json string and there are easier ways to get your data.
You could create a Dictionary<string,object> dict in which there is the name of the property and the property.
You can then split the string,
//Remove the "
initializerString = initializerString.Replace('"', '');
//Split by ,
var tmp = initializerString.Split(",");
//Foreach pair key/value split by :
foreach( var x in tmp){
var tmp2=x.Split(":");
//Assign the value to the property in the Dictionary
dict[tmp2[0]]=tmp2[1];
}
Warning. Since I don't actually know what you're using this code for, this is more of a general idea than working code.
I'm trying to parse a date-formatted file name, e.g.
C:\Documents/<yyyy>\<MMM>\Example_CSV_<ddMM>.csv
and return "Todays" filename.
So for the example above, I would return (for 9th August 2013),
C:\Documents\2013\Aug\Example_CSV_0908.csv
I wondered if Regex would work, but I'm just having a mental block as to how to approach it!
I can't just replace the xth to yth sections with the date, as the files I will be processing are stored in different folders all over the system (not my idea). All of the date codes will be contained in <> however, so as far as I'm aware, I couldn't do something like
Return DateTime.Today.ToString(RawFileName);
Plus I imagine it would have unintended consequences if a part of the ordinary filename could be interpreted as a date code!
If someone could give me a pointer in the right direction, that would be great. If you need a little bit more context, here is the class that will contain this method:
public class ImportSetting
{
public string ID { get; private set; }
public List<ImportMapping> Mappings { get; set; }
public string RawFileName { get; set; }
public string GetFileName()
{
string ToFormat = RawFileName; //e.g. C:\Documents/<yyyy>\<MMM>\Example_CSV_<ddMM>.csv
//Do some clever stuff.
return ToFormat; //C:\Documents\2013\Aug\Example_CSV_0908.csv
}
public int GetCSVColumn(string AttributeName) { return Mappings.First(x => x.Attribute == AttributeName).ColumnID; }
public ImportSetting(string Name)
{
ID = Name;
Mappings = new List<ImportMapping>();
}
}
Thankyou very much for your help!
There is no need to replace anything in the text as you can use the Date.ToString() method with a format string like this:
public string GetFileName(DateTime date)
{
string format = #"'C:\\Documents'\\yyyy\\MMM'\\Example_CSV_'ddMM'.csv'";
return date.ToString(format);
}
Call GetFileName with today's date:
Console.WriteLine(GetFileName(DateTime.Now));
Output:
C:\Documents\2013\Aug\Example_CSV_0908.csv
Anything that you don't want to be parsed as a date, put in single quotes ' to have it parsed as a string literal. A full list of the date format strings can be found here: http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx
var path = new Regex("<([dMy]+)>").Replace(pathFormat, o => DateTime.Now.ToString(o.Groups[1].Value));
Nb: Add all the possible letters/symbols that could occure within the square brackets.
Nb2: This will however not restrict weird DateTime strings. If you want to ensure a uniformed format, you could make a more restrictive Regex like so :
var path = new Regex("<(ddMM)|(MMM)|(yyyy)>").Replace(pathFormat, o => DateTime.Now.ToString(o.Groups[1].Value));
Edit: Gotta love one-liners :)
What you could do (although I can't imagen this is a real scenario but that might be my lacking imagenation is the following regex;
<([fdDmMyYs]+?)>
This will give you any matches within the < and > symbols, as short as possible so in testing for me it returned;
Then strip the first and last symbol, or use some fancier regex functions to do this for you.
Then just use the DateTime.Now.ToString(RegexMatchWithout<> here)
And replace the match with the output.
So a code example (untested, but i'm feeling confident ;-)) would be:
public string GetFileName(string fileName)
{
Regex regex = new Regex(#"<([fdDmMyYs]+?)>");
foreach(Match m in regex.Matches(fileName))
{
fileName = fileName.Replace(m.Value, DateTime.Now.ToString(m.Value.Substring(1, m.Value.Length - 2)));
}
return fileName;
}
I am trying the following stemming class :
static class StemmerSteps
{
public static string stepSufixremover(this string str, string suffex)
{
if (str.EndsWith(suffex))
{
................
}
return str;
}
public static string stepPrefixemover(this string str, string prefix)
{
if (str.StartsWith(prefix)
{
.....................
}
return str;
}
}
this class works with one prefix or suffix. is there any suggestion to allow a list of prefixes or suffixes to go through the class and compare against each (str). your kind action really appreciated.
Instead of creating your own class from scratch (unless this is homework) I would definitive use an existing library. This answer provides an example of code that that implements the Porter Stemming Algorithm:
https://stackoverflow.com/questions/7611455/how-to-perform-stemming-in-c
Put your suffix/prefixes in a collection (like a List<>), and loop through and apply each possible one. This collection would need to be passed into the method.
List<string> suffixes = ...;
for (suffix in suffixes)
if (str.EndsWith(suffix))
str = str.Remove(str.Length - suffix.Length, suffix.Length);
EDIT
Considering your comment:
"just want to look if the string starts-/endswith any of the passed strings"
may be something like this can fit your needs:
public static string stepSufixremover(this string str, IEnumerable<string> suffex)
{
string suf = suffex.Where(x=>str.EndsWith(x)).SingleOrDefault();
if(!string.IsNullOrEmpty(suf))
{
str = str.Remove(str.Length - suf.Length, suf.Length);
}
return str;
}
If you use this like:
"hello".stepone(new string[]{"lo","l"}).Dump();
it produces:
hel
The simplest code would involve regular expressions.
For example, this would identify some English suffixes:
'^(.*?)(ing|ly|ed|ious|ies|ive|es|s|ment)?$'
One problem is that stemming is not as accurate as lemmatization. Lematization would require POS tagging for accuracy. For example, you don't want to add an -ing suffix to dove if it's a noun.
Another problem is that some suffixes also require prefixes. For example, you must add en- to -rich- to add a -ment suffix in en-rich-ment -- unlike a root like -govern- where you can add the suffix without any prefix.