Need to get two values out into an array from string split - c#

I have a string that looks like this:
var result = "y-9m-10y-9m-11y-0m-02y-0m-03";
I need to make 2 lists:
one for all the y- objects(9,9,0,0)
and another for the m- objects(10,11,02,03).
How can I do this?
I have this older code from before that doesn't care about the y- objects. Now I need to get both sets.
var result = "m-10m-11m-02m-03";
var months = result.Split(new[] { "m-" }, StringSplitOptions.RemoveEmptyEntries);

Quick and dirty solution using regular expressions and LINQ:
var months = Regex.Matches(result, #"m-(\d+)").Cast<Match>().Select(m => int.Parse(m.Groups[1].Value));
var years = Regex.Matches(result, #"y-(\d+)").Cast<Match>().Select(m => int.Parse(m.Groups[1].Value));
Note that this doesn't do any error checking.
Edit: In the question you seem to use the extracted strings without converting them to int. In this case, omit the int.Parse and use m.Groups[1].Value directly.

Related

Extract substring between startsequence and endsequence in C# using LINQ

I have an XML instance that contains processing instructions. I want a specific one (the schematron declaration):
<?xml-model href="../../a/b/c.sch" schematypens="http://purl.oclc.org/dsdl/schematron"?>
There may or may not be more than these very processing instructions present, so I can't rely on its position in the DOM; it is guaranteed, on the other hand, that there will be only one (or none) such Schematron file reference. Thus, I get it like so:
XProcessingInstruction p = d.Nodes().OfType<XProcessingInstruction>()
.Where(x => x.Target.Equals("xml-model") &&
x.Data.Contains("schematypens=\"http://purl.oclc.org/dsdl/schematron\""))
.FirstOrDefault();
In the example given, the content of p.Data is the string
href="../../a/b/c.sch" schematypens="http://purl.oclc.org/dsdl/schematron"
I need to extract the path specified via #href (i. e. in this example I would want the string ../../a/b/c.sch) without double quotes. In other words: I need the substring after href=" and before the next ". I'm trying to achieve my goal with LINQ:
var a = p.Data.Split(' ').Where(s => s.StartsWith("href=\""))
.Select(s => s.Substring("href=\"".Length))
.Select(s => s.TakeWhile(c => c != '"'));
I would have thought this gave me a IEnumerable<char> which I could then convert to a string in one of the ways described here, but that's not the case: According to LINQPad, I seem to be getting a IEnumerabale<IEnumerable<char>> which I can't manage to make into a string.
How could this be done correctly using LINQ? Maybe I'd better be using Regex within LINQ?
Edit: After typing this down, I came up with a working solution, but it seems very inelegant:
string a = new string
(
p.Data.Substring(p.Data.IndexOf("href=\"") + "href=\"".Length)
.TakeWhile(c => c != '"').ToArray()
);
What would be a better way?
Try this:
var input = #"<?xml-model href=""../../a/b/c.sch"" schematypens=""http://purl.oclc.org/dsdl/schematron""?>";
var match = Regex.Match(input, #"href=""(.*?)""");
var url = match.Groups[1].Value;
That gives me ../../a/b/c.sch in url.
Please don't use Regex for general XML parsing, but for this situation it's fine.

Compare two comma separated lists in C# to get difference [duplicate]

This question already has answers here:
How to compare 2 List<string> objects to get the missing value from the List<string>
(5 answers)
Closed 2 years ago.
If I have two strings that are both comma separated values and I know there will only be 1 part missing from one of the strings, how can I retrieve that in C#?
Example:
String 1 = "one,two,four"
String 2 = "one,two,three,four"
Result = "three"
I've tried using String.Compare which returns -1 or 1 so I know they are different, but how do I actually pull the value of the difference?
I'd like to have a 3rd string containing the missing value from String 1
Thanks in advance.
Use linq Except both ways and union to get the differences from both.
String[] strs1 = "one,two,four".Split(",");
String[] strs2 = "one,two,three,four".Split(",");
var res = strs1.Except(strs2).Union(strs2.Except(strs1));
String result = String.Join(",",res);
string result = null;
string[] arr1 = 1.Split(','); //Get the first string into array
string[] arr2 = 2.Split(','); //Get the second string into array
//Compare lengths, if arr1 is bigger call Except on it, else on arr2
//Linq .Except will return elements of array which aren't in the parameter array
if(arr1.Length > arr2.Length
{
result = String.Join(" ", arr1.Except(arr2).ToArray());
}
else
{
result = String.Join(" ", arr2.Except(arr1).ToArray());
}
You have to convert the strings to sequences (IEnumerable<string>). Once you have that you can use Except(). The simplest way to do this is String.Split(), though I really hate the method... so many edge cases where this can fall down, and performance isn't even very good. Much better to pull in an actual CSV parser. But for brevity on Stack Overflow:
var string1 = "one,two,four";
var string2 = "one,two,three,four";
var Result = string.Join(",", string2.Split(',').Except(string1.Split(',')));
See it work here:
https://dotnetfiddle.net/l6AkOr
#Olivier Rogier already gave a good answer. Here is some code to understand the concept (his is more efficient).
var split1 = String1.Split(",");
var split 2 = String2.Split(",");
var builder = new StringBuilder();
//other ways to do this, but aiming for illustration of the concept
List<string> list1;
List<string> list2;
if(split1.Length > split2) {
list1 = split1.ToArray();
list2 = split2.ToArray();
}
else {
list2 = split1.ToArray();
list1 = split2.ToArray();
}
foreach(var s in list1)
{
if(!list2.Contains(s))
{
if(builder.Length > 0)
{
builder.Append(",");
}
builder.Append(s);
}
}
This will produce you a list of one or more items (comma separated if 2 or more). I did this freeform, so there might be a typo, so debug.
Once you understand how it works, read the comment #Olivier Rogier made to your post.

MVC/C# Put a comma after every number in string

I have a string of 4 numbers:
1234
I want to convert this in the most elegant way possible in MVC to
1,2,3,4
I've tried this:
codeToSend.ToString("#,#");
but this outputs "1,234" (which I expected really).
I suspected that the following would put a comma after every digit, but to no avail.
codeToSend.ToString("#,#,#,#");
I have also tried string.format, but again I am facing the same issue.
var formattedString = string.Format("{0:0,0}", 1234);
Whats the most efficient way of doing this therefore?
Note:
The string of numbers will always be 4 digits long - and numbers only. I don't want to use Insert as this wouldn't be very elegant IMO and I am aware this question has been asked before in similar ways but it is always slightly different in crucial ways (such as formatting to thousands, not every digit or just not elegantly!).
How about just using string.Join?
int i = 1234;
string.Join(",", i.ToString().ToCharArray()); // 1,2,3,4
If 1234 is string, just use;
string s = "1234";
string.Join(",", s.ToCharArray()); // 1,2,3,4
or
string s = "1234";
string.Join(",", s.ToList()); // 1,2,3,4
This one could be more efficient. (But hardly elegant)
var target = "1234";
var result = Regex.Replace(target , #"(\d)(?=.)", "$1,");
Taking fixed string length into account, the same result could be acomplished without lookahead (simpler for reading, and with better efficiency)
var target = "1234";
var result = Regex.Replace(target, #"(\d)(\d)(\d)(\d)", "$1,$2,$3,$4");
Also, if you are processing many such values, you should compile regex before using.
var target = "1234";
var digitExceptLastRegex = new Regex(#"(\d)(?=.)", RegexOptions.Compiled);
var result = regex.Replace(target, "$1,");
But I haven't measured actual performance.

Remove part of String inside List<string>

I have a List<string> that will have an item in it like 2014-11-03 23:58:37.6750486_0003 and I was wondering how it could strip the following items from the list:2014-11-03 and .6750486_0003, leaving only 23:58:37.
Using the following to add the item to the List:
calltimeList.Add(msg.timestamp().as_creator_time(header.tz_offset()).ToString());
Using this
Console.WriteLine(entryTime.Substring(11, 8));
Works fine since it will always start # 11 and only be 8 characters
You can use LINQ:
List<string> lst = new List<string> { "2014-11-03 23:58:37.6750486_0003" };
List<string> calltimeList = lst.Select(s => new string(s.SkipWhile(c => c != ' ').Skip(1).TakeWhile(c => c != '.').ToArray())).ToList();
Split the string into two parts, then take the first string and use this in your list.
The Split method will return the split string into an array, so you will have the correct part in the first place in the array.
var stringYouWant = msg.timestamp().as_creator_time(header.tz_offset()).ToString().Split(',')[0];
You could substring the the string value or convert to a DateTime then use and formatter to get the desired value.
string timestamp = "2014-11-03 23:58:37.6750486_0003";
int index=timestamp.IndexOf(":");
timestamp.Substring(index - 2, 8);
or
string timestamp = "2014-11-03 23:58:37.6750486_0003";
int index = timestamp.IndexOf("_");
var time = DateTime.Parse(timestamp.Substring(0, index));
you could so something like
var newList= callTimeList.Select(c=>c.Substring(11,8)).ToList();
but I think a better solution would be to store your callTimeList as a list of dates and then stringify it as needed. My initial though was to convert the string into a date and then format it
var newList = callTimeList.Select(c=> String.Format("{0:HH:mm:ss}",c)).ToList();
but I'm not familiar with the _0003 stuff, but it isn't parsable by DateTime.Parse.
A simple SubString would do.
msg.timestamp().as_creator_time(header.tz_offset()).ToString().SubString(11, 8)
However, looks like you are working with a timestamp. If you can get a hold of the DateTime , it's more readable to do something like
myDateTime.ToString("HH:mm:ss")

remove first element from array

PHP developer here working with c#.
I'm using a technique to remove a block of text from a large string by exploding the string into an array and then shifting the first element out of the array and turning what remains back into a string.
With PHP (an awesome & easy language) it was just
$array = explode('somestring',$string);
array_shift($array);
$newstring = implode(' ', $array);
and I'm done.
I get so mad at c# for not allowing me to create dynamic arrays and for not offering me default functions that can do the same thing as PHP regarding arrays. Instead of dynamic arrays I have to create lists and predefine key structures etc. But I'm new and I'm sure there are still equally graceful ways to do the same with c#.
Will someone show me a clean way to accomplish this goal with c#?
Rephrase of question: How can I remove the first element from an array using c# code.
Here is how far I've gotten, but RemoveAt throws a error while debugging so I don't believe it works:
//scoop-out feed header information
if (entry_start != "")
{
string[] parts = Regex.Split(this_string, #entry_start);
parts.RemoveAt(0);
this_string = String.Join(" ", parts);
}
I get so mad at c# for not allowing me to create dynamic arrays
You may take a look at the List<T> class. Its RemoveAt might be worth checking.
But for your particular scenario you could simply use LINQ and the Skip extension method (don't forget to add using System.Linq; to your file in order to bring it into scope):
if (entry_start != "")
{
string[] parts = Regex.Split(this_string, #entry_start).Skip(1).ToArray();
this_string = String.Join(" ", parts);
}
C# is not designed to be quick and dirty, nor it particularly specializes in text manipulation. Furthermore, the technique you use for removing some portion of a string from a beginning is crazy imho.
Why don't you just use String.Substring(int start, int length) coupled with String.IndexOf("your delimiter")?
Here is the corresponding C# code:
string input = "a,b,c,d,e";
string[] splitvals = input.Split(',');
string output = String.Join(",", splitvals, 1, splitvals.Length-1);
MessageBox.Show(output);
You can use LINQ for this:
if (entry_start != "")
this_string = String.Join(" ", Regex.Split(this_string, #entry_start).Skip(1).ToArray());
string split = ",";
string str = "asd1,asd2,asd3,asd4,asd5";
string[] ary = str.Split(new string[] { split }, StringSplitOptions.RemoveEmptyEntries);
string newstr = string.Join(split, ary, 1, ary.Count() - 1);
splits at ",". removes the first record. then combines back with ","
As stated above, you can use LINQ. Skip(int) will return an IEnumerable<string> that you can then cast back as array.
string[] myArray = new string[]{"this", "is", "an", "array"};
myArray = myArray.Skip(1).toArray();
You might be more comfortable with generic lists than arrays, which work more like PHP arrays.
List<T>
But if your goal is "to remove a block of text from a large string" then the easier way would be:
string Example = "somestring";
string BlockRemoved = Example.Substring(1);
// BlockRemoved = "omestring"
Edit
I misunderstood the question, thinking you were just removing the first element from the array where the array consisted of the characters that make up the string.
To split a string by a delimiter, look at the String.Split method instead. Some good examples are given here.

Categories

Resources