Reputation: 1520
I have a string variable that contain [l=9;f=0;r=5;p=2]
. There are may be a more than one:[l=9;f=0;r=5;p=2],[l=9;f=0;r=6;p=2]
.
I want to get List
of Tuple<int,int,int>
, where item1 = value of l, item2= value of r, item3=value of p
. What is best approach to do this?
My code:
// split string
var splittedFormatedSeats = Regex.Matches(formatSeats, @"\[.+?\]")
.Cast<Match>()
.Select(m => m.Value)
.ToList();
IList<Tuple<int,int,int>> fullSeat = new List<Tuple<int, int, int>>();
foreach (var splittedFormatedSeat in splittedFormatedSeats)
{
...
}
Thanks.
Upvotes: 2
Views: 399
Reputation: 37710
I would adopt another strategy. First, split subcomponents of your string
var components = formatSeats.Split(',');
This will give you an array of string. This will be far more efficient to parse small chunks of strings instead of a big string.
You can then use either a Regex
to extract the values or a simple code like this :
foreach(var component in components)
{
var parts = component.Trim("[]".ToCharArray()).Split(';');
}
var results = from component in components
let c = component.Trim("[]".ToCharArray())
.Split(';')
.Select(c=>int.Parse(c.SubString(2))
select new { l = c[0], f=c[1], r=c[2], p = c[3] };
This will produces an enumeration of an anonymous type.
foreach(var x in results)
{
Console.WriteLine("{0} / {1} / {2} / {3}", x.l, x.f, x.r, x.p);
}
If you actually need a Tuple
simply change the code to :
var results = from component in components
let c = component.Trim("[]".ToCharArray())
.Split(';')
.Select(c=>int.Parse(c.SubString(2))
select new Tuple<int,int,int,int>{ l = c[0], f=c[1], r=c[2], p = c[3] };
I would however, advocate for writing a small struct to simplify the code and raise its readability.
public struct MyValue
{
private readonly int m_L;
public int L { get {return m_L; } }
private readonly int m_F;
public int F { get {return m_F; } }
private readonly int m_R;
public int R { get {return m_R; } }
private readonly int m_P;
public int P { get {return m_P; } }
public MyValue(int l, int f, int r, int p)
{
m_L = l;
m_F = f;
m_R = r;
m_P = p;
}
}
....
var results = from component in components
let c = component.Trim("[]".ToCharArray())
.Split(';')
.Select(c=>int.Parse(c.SubString(2))
select new MyValue(c[0],c[1],c[2],c[3]);
Finally, if the string always have this form, you could avoid using the Regex.
Upvotes: 3
Reputation: 2666
string formattedString = "[l=9;f=0;r=5;p=2],[l=9;f=0;r=6;p=2]";
var splitString = formattedString.Split(',')
.Select(p => p.Trim(new char[]{'[',']',' '}));
List<Tuple<int, int, int, int>> tupleList = new List<Tuple<int, int, int, int>>();
foreach (var item in splitString)
{
int[] finalSplit = item.Split(';').Select(p =>
Convert.ToInt32(p.Substring(p.LastIndexOf('=')+1).Trim())
).ToArray();
tupleList.Add(new Tuple<int, int, int, int>(finalSplit[0], finalSplit[1],
finalSplit[2], finalSplit[3]));
}
This will split values of l, f, r and p and add them to the Tuple.
Upvotes: 2
Reputation: 44306
Is the format of your inner string always the same ? Is it always a single digit value for each variable (l, f, r & p)?
If so you can just substring them out.
foreach(var splittedFormatedSeat in splittedFormatedSeats)
{
int x, y, z;
string s = splittedFormatedSeat .ToString();
if(int.TryParse(s[3].ToString(), out x) &&
int.TryParse(s[11].ToString(), out y) &&
int.TryParse(s[15].ToString(), out z))
fullSeat.Add(new Tuple<int,int,int>(x,y,z));
}
Upvotes: 1