I wrote the following regex:
^(\[[0-9]+\])*$
It matches these exemplary texts:
""
"[0]"
"[0][1][2][0][9]"
What I would like to do is to get a list of numbers stored within brackets. How to do this elegantly?
My approach:
public static IEnumerable<int> GetNumbers(string text)
{
if (false == Regex.IsMatch(text, "^(\\[[0-9]+\\])*$"))
throw new FormatException();
return text
.Trim('[', ']')
.Split(new[] {"]["}, StringSplitOptions.None)
.Select(int.Parse);
}
Solution:
public static IEnumerable<int> GetNumbers(string text)
{
var match = Regex.Match(text, "^(\\[(?<number>[0-9]+)\\])*$");
if (!match.Success)
throw new FormatException();
var captures = match.Groups["number"].Captures;
foreach (Capture capture in captures)
yield return int.Parse(capture.Value);
}
If you cannot change the pattern, but only code, you may use
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
public class Test
{
public static void Main()
{
var s1 = "[0][1][2][0][9]";
var res1 = string.Join(",", GetNumbers(s1).ToList()); // Many
Console.WriteLine(res1);
Console.WriteLine(string.Join(",", GetNumbers("[8]").ToList())); // One
Console.WriteLine(string.Join(",", GetNumbers("").ToList())); // Empty
}
public static IEnumerable<int> GetNumbers(string text)
{
if (string.IsNullOrWhiteSpace(text))
return Enumerable.Empty<int>(); // No text => return Empty
var match = Regex.Match(text, #"^(\[[0-9]+\])*$");
if (!match.Success) // No match => return Empty
return Enumerable.Empty<int>();
return match.Groups[1].Captures
.Cast<Capture>() // Get the captures
.Select(n => Int32.Parse(n.Value.Trim('[', ']'))); // Trim the brackets and parse
}
}
See the IDEONE demo
Related
My location list has these values:
Saudi
Arabia
Tokyo
India
Germany
My question when i give input as Saudi Arabia it should take each word in input and compare with the location list if any one the word is present in the list it should give true and that too only using equals method. Please help.
First of all, let's read the file just once:
using System.Linq;
...
// HashSet.Contains is faster then List.Contains: O(1) vs. V(N)
private static HashSet<string> s_Words = new HashSet<string>(File
.ReadLines(#"C:\list\LocationCheckList")
.Where(line => !string.IsNullOrWhiteSpace(line))
.Select(item => item.Trim()),
StringComparer.OrdinalIgnoreCase
);
then you can easily check:
public static bool isExactLocation(string item) {
return item
?.Split(' ', StringSplitOptions.RemoveEmptyEntries)
?.All(word => s_Words.Contains(word)) ?? null;
}
Edit: if you insist on List<strint> and for (foreach) loop:
private static List<string> s_Words = File
.ReadLines(#"C:\list\LocationCheckList")
.Where(line => !string.IsNullOrWhiteSpace(line))
.Select(item => item.Trim())
.ToList();
then we can loop...
public static bool isExactLocation(string item) {
if (null == item)
return false;
string[] words = item
.Split(' ', StringSplitOptions.RemoveEmptyEntries);
foreach (string word in words) {
bool found = false;
foreach (string location in s_Words) {
if (location.Equals(word, StringComparison.OrdinalIgnoreCase)) {
found = true;
break;
}
}
if (!found)
return false;
}
return true;
}
You can do something like
using System.Linq;
LocationCheckList.Any(x=> item.Split(' ').Contains(x))
but watch out for "South Korea vs South Africa"
Input #2: profile.Address.AddressLine1
Result: profile.address.addressLine1
Input #2: MyName
Result: myName
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
string inputText = "profile.Business.AddressLine1"; //profile.business.addressLine1
//string inputText = "MyName"; //myName
string result = null;
if (inputText.Contains('.'))
{
//make first character lowercase
result = inputText.Substring(0, 1).ToLower() + inputText.Substring(1);
//Loop to find period symbol
//make the next character after the period symbol lowercase
}
else
{
//make first character lowercase
result = inputText.Substring(0, 1).ToLower() + inputText.Substring(1);
}
}
}
}
I suggest using regular expressions:
Code:
using System.Linq; // For test only
using System.Text.RegularExpressions;
...
Func<string, string> toCamel = (source) =>
Regex.Replace(source, #"\b\p{Lu}", m => m.Value.ToLower());
string[] tests = new string[] {
#"profile.Business.AddressLine1",
#"MyFunction(Value, SomeId);",
};
string report = string.Join(Environment.NewLine, tests
.Select(test => $"{test,-40} => {toCamel(test)}"));
Console.WriteLine(report);
we Replace every uppercase letter (\p{Lu}) which is preceeded by word boundary (\b) with lowercase one
Outcome:
profile.Business.AddressLine1 => profile.business.addressLine1
MyFunction(Value, SomeId); => myFunction(value, someId);
If you want to convert after . only, just change the pattern into
#"\.\p{Lu}"
You can try below code:
static void Main(string[] args)
{
string inputText = "profile.Business.AddressLine1";
convertToCamelCase(inputText); //profile.business.addressLine1
}
static string convertToCamelCase(string inputText)
{
string result = string.Empty;
if (inputText.Contains('.'))
{
var inputs = inputText.Split('.');
for (int i = 0; i < inputs.Length; i++)
{
inputs[i] = inputs[i].Substring(0, 1).ToLower() + inputs[i].Substring(1);
}
result = string.Join(".", inputs);
}
else
{
result = convertToCamelCase(inputText);
}
return result;
}
Try below:
var input = "profile.Business.AddressLine1";
var result = string.Join(".",
input.Split('.')
.Select(x => string.IsNullOrEmpty(x)
? "" : Char.ToLower(x.First()) + x.Substring(1)));
Steps to solve your issue:
Split your input string using ..
Change your first letter of each word to lower and concatenate rest of the string.
Again join array with .
Try it online
Inputs:
var input = "profile.Business.AddressLine1";
var test = "Test..Test";
Output:
profile.business.addressLine1
test..test
You should use this code:
static string convertToCamelCase(string inputText)
{
string result = string.Empty;
if (string.IsNullOrEmpty(inputText)) return result;
var inputs = inputText.Split('.');
for(int i = 0; i < inputs.Length; i++)
{
if (String.IsNullOrEmpty(inputs[i])) continue;
inputs[i] = inputs[i].Substring(0, 1).ToLower() + inputs[i].Substring(1);
}
result = string.Join(".", inputs);
return result;
}
Problem is below: (need to write ReserveComplemenet method in c#)
The reverse complement of a sequence is formed by exchanging all of its nucleobases with their base complements, and then reversing the resulting sequence. The reverse complement of a DNA sequence is formed by exchanging all instances of:
A with T
T with A
G with C
C with G
Then reversing the resulting sequence.
For example:
Given the DNA sequence AAGCT the reverse complement is AGCTT
This method, ReverseComplement(), must take the following parameter:
Reference to a DNA sequence
This method should return void and mutate the referenced DNA sequence to its reverse complement.
Currently, here is my code,
string result = z.Replace('A', 'T').Replace('T', 'A').Replace('G', 'C').Replace('C', 'G');
string before = (result);
return before;
I'm stuck and wondering how I do this? Any help would be greatly appreciated. When I run this I get AAGGA and not AGCTT
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp8
{
class Program
{
static void Main(string[] args)
{
var dict = new Dictionary<char, char>()
{
['A'] = 'T',
['T'] = 'A',
['G'] = 'C',
['C'] = 'G',
};
var input = "AAGCT";
var output = string.Concat(input.Select(c => dict[c]).Reverse()); // AGCTT
Console.WriteLine(input);
Console.WriteLine(output);
}
}
}
When i run this i get AAGGA and not AGCTT
Because you are looking at it as a single replace, not multiple replaces:
z.Replace('A', 'T').Replace('T', 'A').Replace('G', 'C').Replace('C', 'G');
AAGCT
Replace('A', 'T')
TTGCT
Replace('T', 'A')
AAGCA
Replace('G', 'C')
AACCA
.Replace('C', 'G')
AAGGA
Instead what I would recommend is intermediary replace:
var z = "AAGCT";
var chars = z.Replace('A', '1')
.Replace('T', 'A')
.Replace('1', 'T')
.Replace('G', '2')
.Replace('C', 'G')
.Replace('2', 'C')
.Reverse()
.ToArray();
var result = new string(chars);
Console.WriteLine(result);
Yields:
AGCTT
DotNetFIddle Example
Now if you're doing this millions of times, you may want to consider using a StringBuilder instead.
Recommended reading: The Sad Tragedy of Micro-Optimization Theater
A little trick to Replace-version:
using System;
using System.Linq;
namespace DNA
{
public class Program
{
public static void Main()
{
var dna = "AAGCT";
var reversed = new String(dna
.ToLower()
.Replace('a', 'T')
.Replace('t', 'A')
.Replace('g', 'C')
.Replace('c', 'G')
.Reverse()
.ToArray());
Console.WriteLine(reversed);
}
}
}
Or good old StringBuilder:
using System;
using System.Text;
namespace DNA
{
public class Program
{
public static void Main()
{
var dna = "AAGCT";
var sb = new StringBuilder(dna.Length);
for(var i = dna.Length - 1; i >- 1; i--)
{
switch(dna[i])
{
case 'A':
sb.Append('T');
break;
case 'T':
sb.Append('A');
break;
case 'G':
sb.Append('C');
break;
case 'C':
sb.Append('G');
break;
}
}
var reversed = sb.ToString();
Console.WriteLine(reversed);
}
}
}
Instead of replacing each char, it's easier to implement using linq:
void Translate(ref string dna)
{
var map = new string[] {"AGTC", "TCAG"};
dna = string.Join("", dna.Select(c => map[1][map[0].IndexOf(c)]).Reverse());
}
You start with a string array that represents the mappings - then you select the mapped char for each char of the string, reverse the IEnumerable<char> you get from the Select, and use string.Join to convert it back to a string.
The code in the question first converts A to T, and then convert T to A, so everything that was A returns as an A, but also everything that was T returns as an A as well (same goes for G and C).
And also a non-linq solution based on a for loop and string builder (translation logic is the same):
void Translate(ref string dna)
{
var map = new string[] {"AGTC", "TCAG"};
var sb = new StringBuilder(dna.Length);
for(int i = dna.Length-1; i > -1; i--)
{
sb.Append(map[1][map[0].IndexOf(dna[i])]);
}
dna = sb.ToString();
}
if I have a string along the lines of: "user:jim;id:23;group:49st;"
how can I replace the group code (49st) with something else, so that it shows: "user:jim;id=23;group:76pm;"
sorry if the question is easy but I haven't found a specific answer, just cases different than mine.
You can use the index of "group" like this
string s = "user:jim;id:23;group:49st;";
string newS = s.Substring(0,s.IndexOf("group:") + 6);
string restOfS = s.IndexOf(";",s.IndexOf("group:") + 6) + 1 == s.Length
? ""
: s.Substring(s.IndexOf(";",s.IndexOf("group:") + 6) + 1);
newS += "76pm;";
s = newS + restOfS;
The line with the s = criteria ? true : false is essentially an if but it is put onto one line using a ternary operator.
Alternatively, if you know what text is there already and what it should be replaced with, you can just use a Replace
s = s.Replace("49st","76pm");
As an added precaution, if you are not always going to have this "group:" part in the string, to avoid errors put this inside an if which checks first
if(s.Contains("group:"))
{
//Code
}
Find the match using regex and replace it with new value in original string as mentioned below:
string str = "user:jim;id=23;group:49st;";
var match = Regex.Match(str, "group:.*;").ToString();
var newGroup = "group:76pm;";
str = str.Replace(match, newGroup);
This solution should work no matter where the group appears in the string:
string input = "user:jim;id:23;group:49st;";
string newGroup = "76pm";
string output = Regex.Replace(input, "(group:)([^;]*)", "${1}"+newGroup);
Here is a very generic method for splitting your input, changing items, then rejoining items to a string. It is not meant for single replacement in your example, but is meant to show how to split and join items in string.
I used Regex to split the items and then put results into a dictionary.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string pattern = "(?'name'[^:]):(?'value'.*)";
string input = "user:jim;id:23;group:49st";
Dictionary<string,string> dict = input.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries).Select(x => new
{
name = Regex.Match(x, pattern).Groups["name"].Value,
value = Regex.Match(x, pattern).Groups["value"].Value
}).GroupBy(x => x.name, y => y.value)
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
dict["group"] = "76pm";
string output = string.Join(";",dict.AsEnumerable().Select(x => string.Join(":", new string[] {x.Key, x.Value})).ToArray());
}
}
}
That is just one way to do it. I hope it will help you.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace stringi
{
class Program
{
static void Main(string[] args)
{
//this is your original string
string s = "user:jim;id:23;group:49st";
//string with replace characters
string s2 = "76pm";
//convert string to char array so you can rewrite character
char[] c = s.ToCharArray(0, s.Length);
//asign characters to right place
c[21] = s2[0];
c[22] = s2[1];
c[23] = s2[2];
c[24] = s2[3];
//this is your new string
string new_s = new string(c);
//output your new string
Console.WriteLine(new_s);
Console.ReadLine();
}
}
}
string a = "user:jim;id:23;group:49st";
string b = a.Replace("49st", "76pm");
Console.Write(b);
I have a string with some letters and numbers. here an exemple :
OG000134W4.11
I have to trim all the first letters and the first zeros to get this :
134W4.11
I also need to cut the character from the first letter he will encounter to finally retreive :
134
I know I can do this with more than one "trim" but I want to know if there was an efficient way to do that.
Thanks.
If you don't want to use regex.. then Linq is your friend
[Test]
public void TrimTest()
{
var str = "OG000134W4.11";
var ret = str.SkipWhile(x => char.IsLetter(x) || x == '0').TakeWhile(x => !char.IsLetter(x));
Assert.AreEqual("134", ret);
}
Here is the regex I would use
([1-9][0-9]*)[^1-9].*
Here is some C# code you could try
var input = "OG000134W4.11";
var result = new Regex(#"([1-9][0-9]*)[^1-9].*").Replace(input, "$1");
using System;
using System.Text.RegularExpressions;
namespace regex
{
class MainClass
{
public static void Main (string[] args)
{
string result = matchTest("OG000134W4.11");
Console.WriteLine(result);
}
public static string matchTest (string input)
{
Regex rx = new Regex(#"([1-9][0-9]+)\w*[0-9]*\.[0-9]*");
Match match = rx.Match(input);
if (match.Success){
return match.Groups[1].Value;
}else{
return string.Empty;
}
}
}
}