I have a bunch of strings that I'm trying to parse the date out of. I have a script that will parse the date, but it's having trouble with all the extra letters in the string. I need to remove all the letters but leave characters such as - / _
I'm not particularly good with Regex, so all attempts to do this so far have ended with too many characters getting removed.
Here's a few sample strings to help:
Littleton, CO - Go-Live 5/8
Brunswick - Go-Live 5/14
CutSheeet_Go Live-5-14-14
Go Live - 5-19-2014
You could do this:
Regex.Replace(input, "([a-zA-Z,_ ]+|(?<=[a-zA-Z ])[/-])", "");
Working regex example:
http://regex101.com/r/kD2jF4
From your example data, output would be:
5/8
5/14
5-14-14
5-19-2014
You can use a function like this:
public static string Parse(string source)
{
var numbers = new [] {'0','1','2','3','4','5','6','7','8','9' };
var chars = new [] { '-', '/', '_' };
return new string(source
.Where(x => numbers.Contains(x) || chars.Contains(x))
.ToArray()).Trim(chars);
}
Here is fiddle
Try this:
public static string StripCrap(string input)
{
return input.Where(c => char.IsNumber(c) || c == '_' || c == '/' ||
c == '-').Aggregate("", (current, c) => current + c);
}
Or, if you want a maintainable list:
public static string StripCrap(string input)
{
char[] nonCrapChars = {'/', '-', '_'};
return input.Where(c => char.IsNumber(c) || nonCrapChars.Contains(c)).Aggregate("", (current, c) => current + c);
}
Or...You could also create an extension method:
public static string ToNonCrappyString(this string input)
{
char[] nonCrapChars = {'/', '-', '_'};
return input.Where(c => char.IsNumber(c) || nonCrapChars.Contains(c)).Aggregate("", (current, c) => current + c);
}
and you can call it like this:
string myString = "Hello 1234!";
string nonCrappyString = myString.ToNonCrappyString();
use this pattern .*?(\d+[\d-\/]*\d+)|.* and replace with $1 Demo
Related
I've tried some answers from Stackoverflow but they don't count register of the symbols. For example
sTreSS => T (not 's'),
stress => t
Here is what i tried
public static char FirstNonRepeatedCharacter(string s)
{
var output = s.GroupBy(item => item).First(x => x.Count() == 1).Key;
return output;
}
I need to edit the code with case-insensitive and return the correct register
sEVeraL -> s; - SomeBody - S
This is exactly what you need, but not fully in LINQ. In my opinion, you don't have to strictly rely on LINQ...
Console.WriteLine(FirstNonRepeatedCharacter("sTreSS"));
Console.WriteLine(FirstNonRepeatedCharacter("stress"));
Console.WriteLine(FirstNonRepeatedCharacter("sEVeraL"));
Console.WriteLine(FirstNonRepeatedCharacter("SomeBody"));
Console.WriteLine(FirstNonRepeatedCharacter("AaBbCc"));
Console.ReadKey();
static char? FirstNonRepeatedCharacter(string s)
{
// Gather the count for each character (case insensitive, example: 's' and 'S' is in the same group).
var counts = new Dictionary<char, int>();
foreach (var ch in s.ToLower())
{
counts[ch] = counts.TryGetValue(ch, out var count)
? count + 1
: 1;
}
// Return first character with count 1.
return s.FirstOrDefault(ch => counts[char.ToLower(ch)] == 1);
}
Output is:
T
t
s
S
nothing (null)
You can group by characters as they are, but by processed character:
.GroupBy(c => char.ToLower(c), c => c)
Code:
// either first not repeating character or '\0'
private static char FirstNonRepeatedCharacter(string s) => s
?.GroupBy(c => char.ToLower(c), c => c)
?.FirstOrDefault(g => g.Count() == 1)
?.First()
?? '\0';
Edit: if you want to return string - "...I need to return an empty string..." -, you can group by string while providing required comparer:
private static string FirstNonRepeatedCharacter(string s) => s
?.GroupBy(c => c.ToString(), StringComparer.OrdinalIgnoreCase)
?.FirstOrDefault(g => g.Count() == 1)
?.Key
?? "";
I am trying to sort a string split by comma. But it is not behaving as expected
var classes = "10,7,8,9";
Console.Write(string.Join(",", classes.Split(',').OrderBy(x => x)));
Console.ReadKey();
and output is
10,7,8,9
But I want the expected output to be like:
7,8,9,10
Classes can have a section along with them. like 7a,7b
and I want to achieve it on one line of code.
You can use Regex like this
var classes = "10,7,8,9";
Regex number = new Regex(#"^\d+");
Console.Write(string.Join(",", classes.Split(',').OrderBy(x => Convert.ToInt32(number.Match(x).Value)).ThenBy(x => number.Replace(x, ""))));
Console.ReadKey();
CODE:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Collections;
namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
var l = new List<string> { "1D", "25B", "30A", "9C" };
l.Sort((b, a) =>
{
var x = int.Parse(Regex.Replace(a, "[^0-9]", ""));
var y = int.Parse(Regex.Replace(b, "[^0-9]", ""));
if (x != y) return y - x;
return -1 * string.Compare(a, b);
});
foreach (var item in l) Console.WriteLine(item);
}
}
}
OUTPUT:
1D
9C
25B
30A
ONLINE COMPILE:
http://rextester.com/CKKQK66159
Use the following using-directive:
using System.Text.RegularExpressions;
And try the following:
var input = "7,7a,8,9a,9c,9d,10";
var sorted = from sp in input.Split(',')
let reg = Regex.Match(sp, #"(?<num>[0-9]+)(?<char>[a-z]*)", RegexOptions.IgnoreCase | RegexOptions.Compiled)
let number = int.Parse(reg.Groups["num"].ToString())
orderby reg.Groups["char"].ToString() ascending // sort first by letter
orderby number ascending // then by number
select sp;
var result = string.Join(",", sorted);
Console.WriteLine(result);
//output (tested): 7,7a,8,9a,9c,9d,10
It uses regex to determine the numeric and alphabetic part of the input string.
The regex pattern uses named groups, which are noted as follows: (?<group_name> regex_expr ).
The time complexity of the code above is O(n log(n)), in case you are worried about big collections of numbers.
More information about named Regex groups.
More information about LINQ.
... and about the orderby-clause.
All on one line, also supports '4a' etc.
edit: On testing this, a string such as 1,2,111,3 would display as 111,1,2,3, so may not quite be what you're looking for.
string str = "1,2,3,4a,4b,5,6,4c";
str.Split(',').OrderBy(x => x).ToList().ForEach(x=> Console.WriteLine(x));
Console.ReadKey();
Here is my implementation:
IEnumerable<Tuple<string, string[]>> splittedItems =
items.Select(i => new Tuple<string, string[]>(i, Regex.Split(i, "([0-9]+)")));
List<string> orderedItems = splittedItems.OrderBy(t => Convert.ToInt16(t.Item2[1]))
.ThenBy(t => t.Item2.Length > 1 ? t.Item2[2] : "1")
.Select(t => t.Item1).ToList();
Split the input to a number and non numeric characters
Store the splitted strings with their parent string
Order by number
Then order by non numeric characters
Take the parent string again after sorting
The result is like required: { "10", "7", "8b", "8a", "9" } is sorted to { "7", "8a", "8b", "9", "10" }
You are sorting strings (alphabetically), so yes, "10" comes before "7".
My solution converts "10,7b,8,7a,9b" to "7a,7b,8,9b,10" (first sort by the integer prefix, then by the substring itself).
Auxiliary method to parse the prefix of a string:
private static int IntPrefix(string s)
=> s
.TakeWhile(ch => ch >= '0' && ch <= '9')
.Aggregate(0, (a, c) => 10 * a + (c - '0'));
Sorting the substrings by the integer prefix then by the string itself:
classes.Split(',') // string[]
.Select(s => new { s, i = IntPrefix(s) }) // IEnumerable<{ s: string, i: int }>
.OrderBy(si => si.i) // IEnumerable<{ s: string, i: int }>
.ThenBy(si => si.s) // IEnumerable<{ s: string, i: int }>
.Select(si => si.s) // IEnumerable<string>
One liner (with string.Join):
var result = string.Join(",", classes.Split(',').Select(s => new {s, i = IntPrefix(s)}).OrderBy(si => si.i).ThenBy(si => si.s).Select(si => si.s));
I have a string
string test1 = "255\r\n\r\n0\r\n\r\n-1\r\n\r\n255\r\n\r\n1\r";
I want to find all the 1's in my string but not the -1's. So in my string there is only one 1. I use string.Contain("1") but this will find two 1's. So how do i do this?
You can use regular expression:
string test1 = "255\r\n\r\n0\r\n\r\n-1\r\n\r\n255\r\n\r\n1\r";
// if at least one "1", but not "-1"
if (Regex.IsMatch(test1, "(?<!-)1")) {
...
}
the pattern is exactly 1 which is not preceed by -. To find all the 1s:
var matches = Regex
.Matches(test1, "(?<!-)1")
.OfType<Match>()
.ToArray(); // if you want an array
Try this simple solution:
Note : You can convert this to extension Method Easily.
static List<int> FindIndexSpecial(string search, char find, char ignoreIfPreceededBy)
{
// Map each Character with its Index in the String
var characterIndexMapping = search.Select((x, y) => new { character = x, index = y }).ToList();
// Check the Indexes of the excluded Character
var excludeIndexes = characterIndexMapping.Where(x => x.character == ignoreIfPreceededBy).Select(x => x.index).ToList();
// Return only Indexes who match the 'find' and are not preceeded by the excluded character
return (from t in characterIndexMapping
where t.character == find && !excludeIndexes.Contains(t.index - 1)
select t.index).ToList();
}
Usage :
static void Main(string[] args)
{
string test1 = "255\r\n\r\n0\r\n\r\n-1\r\n\r\n255\r\n\r\n1\r";
var matches = FindIndexSpecial(test1, '1', '-');
foreach (int index in matches)
{
Console.WriteLine(index);
}
Console.ReadKey();
}
You could use String.Split and Enumerable.Contains or Enumerable.Where:
string[] lines = test1.Split(new[] {Environment.NewLine, "\r"}, StringSplitOptions.RemoveEmptyEntries);
bool contains1 = lines.Contains("1");
string[] allOnes = lines.Where(l => l == "1").ToArray();
String.Contains searches for sub-strings in a given string instance. Enumerable.Contains looks if there's at least one string in the string[] which equals it.
I have code that finds largest word that starts with a capital letter. But I need that word to add a separator and space. Any ideas how I should do it properly?
char[] skyrikliai = { ' ', '.', ',', '!', '?', ':', ';', '(', ')', '\t' };
string eilute = "Arvydas (g. 1964 m. gruodzio 19 d. Kaune)– Lietuvos, krepsininkas, olimpinis ir pasaulio cempionas, nuo 2011 m. spalio 24 d.";
static string Ilgiausias(string eilute, char[] skyrikliai)
{
string[] parts = eilute.Split(skyrikliai,
StringSplitOptions.RemoveEmptyEntries);
string ilgiaus = "";
foreach (string zodis in parts)
if ((zodis.Length > ilgiaus.Length) && (zodis[0].ToString() == zodis[0].ToString().ToUpper()))
ilgiaus = zodis;
return ilgiaus;
}
It should find word Lietuvos and add , and space
Result should be "Lietuvos, "
I would use LINQ for that:
var ilgiaus = parts.Where(s => s[0].IsUpper())
.OrderByDescending(s => s.Length)
.FirstOrDefault();
if(ilgiaus != null) {
return ilgiaus + ", ";
}
Also you can use regex and linq. You dont need to split by many characters.
Regex regex = new Regex(#"[A-Z]\w*");
string str = "Arvydas (g. 1964 m. gruodzio 19 d. Kaune)– Lietuvos, krepsininkas, olimpinis ir pasaulio cempionas, nuo 2011 m. spalio 24 d.";
string longest = regex.Matches(str).Cast<Match>().Select(match => match.Value).MaxBy(val => val.Length);
if you dont want to use MoreLinq, instead of MaxBy(val => val.Length) you can do OrderByDescending(x => x.Length).First()
There are probably more ingenious and elegant ways, but the following pseudocode should work:
List<String> listOfStrings = new List<String>();
// add some strings to the generic list
listOfStrings.Add("bla");
listOfStrings.Add("foo");
listOfStrings.Add("bar");
listOfStrings.Add("Rompecabeza");
listOfStrings.Add("Rumpelstiltskin");
. . .
String longestWorld = String.Empty;
. . .
longestWord = GetLongestCapitalizedWord(listOfStrings);
. . .
private String GetLongestCapitalizedWord(List<String> listOfStrings)
{
foreach (string s in listofstrings)
{
if ((IsCapitalized(s) && (s.Len > longestWord.Len)))
{
longestWord = s;
}
}
}
private bool IsCapitalized(String s)
{
return // true or false
}
The string is returned the same as it enters the function:
public static string AlphaSort(string S)
{
var NewS = new List<string>();
var Arr = S.Replace(" ", "").Split();
NewS = Arr.ToList();
var SortedS = NewS.OrderBy(c => c).ToList();
return String.Join("", SortedS.ToArray());
}
I have also tried NewS.Sort() to no avail
I think you're overthinking things. Try something like:
public static string AlphaSort( string s )
{
string sorted = string.Join( "" ,
( s ?? "")
.Split()
.OrderBy( x => x )
) ;
return sorted ;
}
which turns this string
"The Quick Brown Fox Jumped Over The Lazy Dog"
into this string
"BrownDogFoxJumpedLazyOverQuickTheThe"
If you're trying to order the individual characters, it gets much easier. A string is an IEnumerable<char> (very convenient). It's also readily convertable to a char[] (since that's ultimately its backing store). In this case, something like
public static string AlphaSort( string s )
{
string sorted = new string(
(s ?? "")
.Where( c => !char.IsWhiteSpace(c) )
.OrderBy( c => c )
);
return sorted ;
}
Given the input noted above,
"The Quick Brown Fox Jumped Over The Lazy Dog"
this produces the string
"BDFJLOQTTacdeeeeghhikmnoooprruuvwxyz"
One might note that once you're looking at characters, the ordering is no longer really alphabetic. Rather, it's an ordinal sort, since a char is an unsigned short.
Here's another approach
public static string AlphaSort( string s )
{
char[] chars = s.ToCharArray() ;
Array.Sort( chars ) ;
int i = 0 ;
while ( i < chars.Length && char.IsWhiteSpace(chars[i]) ) ++i ;
string sorted = new string( chars , i , chars.Length-i ) ;
return sorted ;
}
producing the same
"BDFJLOQTTacdeeeeghhikmnoooprruuvwxyz"
from
"The Quick Brown Fox Jumped Over The Lazy Dog"
Cheers!
I think you're trying to take a string and return the characters alphabetically. If so, try this
public static string AlphaSort(string S)
{
var Arr = S.Replace(" ", "").ToCharArray();
var SortedS = Arr.OrderBy(c => c);
return String.Join("", SortedS);
}
public static string AlphaSort(string S)
{
var Arr = S.Replace(" ", "").Split(' ');
var NewS = Arr.ToList();
var SortedS = NewS.OrderBy(c => c).ToList();
return String.Join("", SortedS.ToArray());
}
or simply you could use without using Replace:
var Arr = S.Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries)
This will return the string sorted case insensitive
public static string AlphaSort(string S)
{
string[] NewS = S.Split(' ');
Array.Sort(NewS, new CaseInsensitiveComparer());
return String.Join(" ", NewS);
}