how to split string into two strings when it finds a number - c#

So basically if I have string a = "asd333"; I want to split this string into two strings
string b = "asd" and string c = "333"
for example string a = "aaa 555";string[]b = a.Split(' '); will make
b[0]="aaa" and b[1] = "555"
But this is not what i want i want to split string into two string withouth loosing characters and split it before a number
This is my code so far
string text = textBox4.Text.ToString();
char[] whitespace = new char[] { ' ','\t' };
string[] temp = text.Split(whitespace);
But i want to change it so string[] temp equals two string first is letters and second is numbers

I think it's not the best method, but it works
string a = "aaa333aaa333aaa22bb22bb1c1c1c";
List<string> result = new List<string>();
int lastSplitInedx = 0;
for (int i = 0; i < a.Length-1; i++)
{
if (char.IsLetter(a[i]) != char.IsLetter(a[i + 1]))
{
result.Add(a.Substring(lastSplitInedx, (i + 1) - lastSplitInedx));
lastSplitInedx = i+1;
}
if (i+1 == a.Length-1)
{
result.Add(a.Substring(lastSplitInedx));
}
}
foreach (string s in result)
{
Console.WriteLine(s);
}

Get the matched group from index 1 and 2.
String literals for use in programs:
C#
#"(\D+)\s*(\d+)"

Search for the integer in the string and split the string at that position
string a = "str123";
string b = string.Empty;
int val;
for (int i=0; i< a.Length; i++)
{
if (Char.IsDigit(a[i]))
b += a[i];
}
if (b.Length>0)
val = int.Parse(b);

Related

How to find substrings of length m that contain ith element(C#)

We have a string length of n, I want to find all substrings of length m that contain ith element.
For example string s = "abcde"; I want to get all substrings of length 3 that contain 2nd element i.e. "b", in this case
abc, bcd
that is 2. But how we can code this for a general situation, i.e. substrings of length m, from a string of length n, that contain ith element
It would be good if substrings are stored in List<string>(not just Console.WriteLine())
public static List<string> GetSubStrings_i(string inputString, int mainIndex, int sbstrLength)
{
List<string> substringsList = new List<string>();
for (int i = mainIndex - sbstrLength + 1; i <= mainIndex; i++)
{
if (i < 0)
i = 0;
if (i + sbstrLength <= inputString.Length)
substringsList.Add(inputString.Substring(i, sbstrLength));
}
return substringsList;
}
"*" is a symbol that all substrings should contain
Input
String = fsaf*faj;aijefaejsk
substrLength = 5
Index = 4
Output
substring = fsaf*
substring = saf*f
substring = af*fa
substring = f*faj
substring = *faj;
Try This:
First you call getAllSubstrings, return list of all substrings of length m that contain i th element
List<String> matchsubstring = getAllSubstrings("abcde","b");
public static List<String> getAllSubstrings(String inputString, String stringmatch)
{
List<String> resultList = new List<String>();
for(int j = 0; j < inputString.Length; j++)
{
for(int i = 0; i < inputString.Length - j + 1 ;i++)
{
if(inputString.Substring(i,j).Contains(stringmatch))
{
resultList.Add(inputString.Substring(i,j));
Console.WriteLine("Substring Length : "+j +
", Substring :" + inputString.Substring(i,j) +
", Index of string match :"+ inputString.Substring(i,j).IndexOf(stringmatch.ToCharArray()[0]));
}
}
}
return resultList;
}
Then you call getAllMatchSubstringByIndexing , return list of all substrings of length m that contain i th element at x index
List<String> outputList = getAllMatchSubstringByIndexing (matchsubstring ,"b",1)
matchsubstring is output of getAllSubstrings function
public static List<String> getAllMatchSubstringByIndexing(List<string> substring, String stringmatch, int index)
{
List<String> substringWithIndex = new List<String>();
foreach(var substringData in substring)
{
if(substringData.IndexOf(stringmatch.ToCharArray()[0]) == index)
{
substringWithIndex.Add(substringData);
Console.WriteLine("Output : "+substringData);
}
}
return substringWithIndex;
}

Get Last Four word after splitting a string

I have two string like below
var str1 = '20180215.20150215.3.1.0.0';
var str2 = '20180215.3.1.0.0';
I need to get the last four word after splitting these string with .
var str1Arr = str1.split('.')
What i need is a generic method to get last four words 3.1.0.0.
Thanks
var lastFour = str1Arr.Reverse().Take(4).Reverse().ToArray();
public static class SplitExtension
{
public static string LastNItems(this string str, int nItem, char separator = '.')
{
return string.Join(separator.ToString(), str.Split(separator).Reverse().Take(nItem).Reverse());
}
public static string[] LastNItems(this string[] strArray, int nItem)
{
return strArray.Reverse().Take(nItem).Reverse().ToArray();
}
}
This will enable you to do
var str1 = "20180215.20150215.3.1.0.0";
var str1Last4 = str1.LastNItems(4); // "3.1.0.0"
var str1Last4Items = str1.Split('.').LastNItems(4); // ["3","1","0","0"]
or for completion
var str1Last4Items = str1.LastNItems(4).Split('.'); // ["3","1","0","0"]
You can use it by extension methods.
public static class CommonExtension
{
public static List<string> LastNItem(this string str, int nItem, string separator = ".")
{
var splittedWords = str.Split(new [] { separator }, StringSplitOptions.None);
var res = splittedWords.Reverse().Take(nItem).Reverse().ToList();
return res;
}
}
Then you can call it everywhere you want.
var str1 = "1.0.0";
var str2 = "20180215.3.1.0.0";
var str1Last4 = str1.LastNItem(4);
var str2Last4 = str2.LastNItem(4);
Why not just Skip top Length - 4 items?
string str1 = "20180215.20150215.3.1.0.0";
string[] str1Arr = str1.Split('.');
var result = str1Arr
.Skip(str1Arr.Length - 4)
.ToArray(); // if you want an array materialization
This code will do even when str1Arr.Length < 4 (in this case the entire str1Arr copy will be returned). In case you want a string as the result you can just try Substring (without creating any arrays)
string str1 = "20180215.20150215.3.1.0.0";
string result = str1;
int index = result.Length;
for (int i = 0; i < 4; ++i) {
index = str1.LastIndexOf('.', index - 1);
if (index < 0)
break;
}
result = index < 0 ? result : result.Substring(index + 1);
public static string GetLastFour(string str)
{
string[] arr = str.Split('.');
System.Text.StringBuilder lastFour = new System.Text.StringBuilder();
if (arr.Length >= 4)
{
for (int k = arr.Length - 4; k < arr.Length; k++)
{
if (k == arr.Length - 1)
{
lastFour.Append(arr[k]);
}
else
{
lastFour.Append(arr[k] + ".");
}
}
}
return lastFour.ToString();
}
This would be faster than double reverse answer.
var str1 = "20180215.20150215.3.1.0.0";
var str2 = "20180215.3.1.0.0";
var words = str1.Split('.');
var toSkip = words.Length - 4;
var result = string.Join(".", words.Skip(toSkip));
A bit of testing showed that is is just slightly faster than double reverse.
What is 10 times faster than this one?
Well avoiding memory allocations and enumerations will be.
Here are the results of comparing 3 different extension methods for 10M iterations:
double reverse: 6463ms
split + skip: 5269ms
straight: 492ms
void Main()
{
var str1 = "20180215.20150215.3.1.0.0";
var numIterations = 10000000;
var timer = new Stopwatch();
timer.Start();
for (var i = 0; i < numIterations; i++)
{
str1.LastNItemsDoubleReverse(4);
}
timer.Stop();
timer.ElapsedMilliseconds.Dump("double reverse");
timer.Reset();
timer.Start();
for (var i = 0; i < numIterations; i++)
{
str1.LastNItemsSplitNSkip(4);
}
timer.Stop();
timer.ElapsedMilliseconds.Dump("split + skip");
timer.Reset();
timer.Start();
for (var i = 0; i < numIterations; i++)
{
str1.LastNItemsStraight(4);
}
timer.Stop();
timer.ElapsedMilliseconds.Dump("straight");
}
public static class ext
{
public static string LastNItemsDoubleReverse(this string str, int nItem, char separator = '.')
{
return string.Join(separator.ToString(), str.Split(separator).Reverse().Take(nItem).Reverse());
}
public static string LastNItemsSplitNSkip(this string str, int nItem, char separator = '.')
{
var words = str.Split(separator);
var toSkip = words.Length - nItem;
return string.Join($"{separator}", words.Skip(toSkip));
}
public static string LastNItemsStraight(this string str, int nItem, char separator = '.')
{
int j=1,i=str.Length-1;
for (;i>=0 && j<nItem;i--){
if(str[i]==separator) j++;
}
return str.Substring(i);
}
}
Try the following :
List<string> GetLastFourWords()
{
List<string> lastFour = new List<string>();
try
{
string[] arr = str1.split('.');
for(int i = 3; i >= 0; i-- )
{
lastFour.Add(arr[str1.length - 1 - i]);
}
}
catch(Exception ex)
{
}
return lastFour;
}

Split string into array of words

I want to split a string into an array of words without using string.Split. I tried already this code and it is working but cant assign the result into the array
string str = "Hello, how are you?";
string tmp = "";
int word_counter = 0;
for (int i = 0; i < str.Length; i++)
{
if (str[i] == ' ')
{
word_counter++;
}
}
string[] words = new string[word_counter+1];
for (int i = 0; i < str.Length; i++)
{
if (str[i] != ' ')
{
tmp = tmp + str[i];
continue;
}
// here is the problem, i cant assign every tmp in the array
for (int j = 0; j < words.Length; j++)
{
words[j] = tmp;
}
tmp = "";
}
You just need a kind of index pointer to put up your item one by one to the array:
string str = "Hello, how are you?";
string tmp = "";
int word_counter = 0;
for (int i = 0; i < str.Length; i++) {
if (str[i] == ' ') {
word_counter++;
}
}
string[] words = new string[word_counter + 1];
int currentWordNo = 0; //at this index pointer
for (int i = 0; i < str.Length; i++) {
if (str[i] != ' ') {
tmp = tmp + str[i];
continue;
}
words[currentWordNo++] = tmp; //change your loop to this
tmp = "";
}
words[currentWordNo++] = tmp; //do this for the last assignment
In my example the index pointer is named currentWordNo
Try using regular expressions, like this:
string str = "Hello, how are you?";
// words == ["Hello", "how", "are", "you"]
string[] words = Regex.Matches(str, "\\w+")
.OfType<Match>()
.Select(m => m.Value)
.ToArray();
String.Split is not a good option since there are too many characters to split on: ' ' (space), '.', ',', ';', '!' etc.
Word is not just a stuff between spaces, there are punctuations to consider, non-breaking spaces etc. Have a look at the input like this:
string str = "Bad(very bad) input to test. . ."
Note
Absence of space after "Bad"
Non-breaking space
Addition spaces after full stops
And the right output should be
["Bad", "very", "bad", "input", "to", "test"]
You can also use a List to create your words list:
string str = "Hello, how are you?";
string tmp = "";
List<string> ListOfWords = new List<string>();
int j = 0;
for (int i = 0; i < str.Length; i++)
{
if (str[i] != ' ')
{
tmp = tmp + str[i];
continue;
}
// here is the problem, i cant assign every tmp in the array
ListOfWords.Add(tmp);
tmp = "";
}
ListOfWords.Add(tmp);
In this way you can avoid to count the number of word and the code is more simple. Use ListOfWord[x] to read any word

How to check if file contains strings, which will double repeat sign?

I would like to check if file containing some strings, separated with # contains double repeat sign. Example:
I have a file like this:
1234#224859#123567
I am reading this file and putting strings separated with # it into array.
I would like to find which strings have a digit repeated next to each other (in this case 224859) and return position of first digit that repeats in this string?
This is what I have so far:
ArrayList list = new ArrayList();
OpenFileDialog openFile1 = new OpenFileDialog();
int size = -1;
DialogResult dr = openFile1.ShowDialog();
string file = openFile1.FileName;
try
{
string text = File.ReadAllText(file);
size = text.Length;
string temp = "";
for (int i = 0; i < text.Length; i++)
{
if (text[i] != '#')
{
temp += text[i].ToString();
}
else
{
list.Add(temp);
temp = "";
}
}
}
catch (IOException)
{
}
string all_values = "";
foreach (Object obj in list)
{
all_values += obj.ToString() + " => ";
Console.WriteLine(" => ", obj);
}
textBox1.Text = (all_values);
This regex should do the trick.
var subject = "1234#224859#123567";
foreach(var item in subject.Split('#'))
{
var regex = new Regex(#"(?<grp>\d)\k<grp>");
var match =regex.Match(item);
if(match.Success)
{
Console.WriteLine("Index : {0}, Item:{1}", match.Index, item);
//prints Index : 0, Item:224859
}
}
This is a more procedural approach than Sriram's, but the main benefit is remembering your results in order to use them later in your program.
Basically, the string is split based on the # delimiter, which returns a string[] which holds each number inside. Then, for each string you iterate through the characters and check to see if the current character at i matches the next character at i + 1. If so, the earliest appearance of a duplicate digit is at i, so i is remembered and we break out of the loop that processes chars.
Since int is a non-nullable type, I decided to use -1 to indicate that a match was not found in a string.
Dictionary<string, int> results = new Dictionary<string, int>();
string text = "1234#224859#123567#11#4322#43#155";
string[] list = text.Split('#');
foreach (string s in list)
{
int tempResult = -1;
for (int i = 0; i < s.Length - 1; i++)
{
if(s.ElementAt(i) == s.ElementAt(i + 1))
{
tempResult = i;
break;
}
}
results.Add(s, tempResult);
}
foreach (KeyValuePair<string, int> pair in results)
{
Console.WriteLine(pair.Key + ": " + pair.Value);
}
Output:
1234: -1
224859: 0
123567: -1
11: 0
4322: 2
43: -1
155: 1
here's another Regex that works
int indexof = -1;
String input = "3492883#32280948093284#990303294";
string[] numbers = input.Split('#');
foreach(string n in numbers)
{
Match m=Regex.Match(n, #"(\d)\1+");
if (m.Success)
{
indexof = m.Index;
}
}
Would this do what you are looking for?
string text = File.ReadAllText(file);
string[] list = text.Split(new char[] { '#' });
Then, after you have the strings separated:
foreach (string s in list)
{
int pos = HasDoubleCharacter(s);
if (pos > -1)
{
// do something
}
}
private static int HasDoubleCharacter(string text)
{
int pos = 0;
char[] c3 = text.ToCharArray();
char lastChar = (char)0;
foreach (char c in c3)
{
if (lastChar == c)
return pos;
lastChar = c;
pos++;
}
return -1;
}
Or are you just looking for the list of positions of all doubles in the original text. If so (and you don't need to act on the various strings separately, you might try this:
private static List<int> FindAllDoublePositions(string text)
{
List<int> positions = new List<int>();
char[] ca = text.ToCharArray();
char lastChar = (char)0;
for (int pos = 0; pos < ca.Length; pos++)
{
if (Char.IsNumber(ca[pos]) && lastChar == ca[pos])
positions.Add(pos);
lastChar = ca[pos];
}
return positions;
}
If your looking for a specific string pattern, Regex is most likely to be your best friend :
string text = "1234#224859#123567asdashjehqwjk4234#244859#123567asdhajksdhqjkw1434#244859#123567";
var results = Regex.Matches(text, #"\d{4}#(?<Value>\d{6})#\d{4}");
var allValues = "";
foreach (Match result in results)
{
allValues = result.Groups["Value"].Value + " => ";
Console.WriteLine(" => ", result.Value);
}

Function that generates strings according to input

I need a C# function that takes 2 strings as an input and return an array of all possible combinations of strings.
private string[] FunctionName(string string1, string string2)
{
//code
}
The strings input will be in the following format:
string1: basement
string2: a*fa
Now what I need is all combinations of possible strings using the characters in String2 (ignoring the * symbols), and keeping them in the same character position like this:
baaement, baaefent, baaefena, basefent, basemena, etc.
EDIT:
This is not homework. I need this function for a piece of a program I am doing.
The following is the code I have so far but it has some bugs.
static List<string> combinations = new List<string>();
static void Main(string[] args)
{
//include trimming of input string
string FoundRes = "incoming";
string AltRes = "*2*45*78";
List<int> loc = new List<int>();
string word = "";
for (int i = 0; i < AltRes.Length; i++)
{
if (AltRes[i] != '*')
{
loc.Add(i);
word += AltRes[i];
}
}
generate(word);
string[] aaa = InsertSymbol(FoundRes, loc.ToArray(), AltRes, combinations);
Console.WriteLine("input string: " + FoundRes);
Console.WriteLine("Substitute string: " + AltRes);
Console.WriteLine("============Output============");
for (int j = 0; j < aaa.Length; j++)
{
Console.WriteLine(aaa[j]);
}
Console.ReadKey();
}//
private static void generate(string word)
{
// Add this word to combination results set
if (!combinations.Contains(word))
combinations.Add(word);
// If the word has only one character, break the recursion
if (word.Length == 1)
{
if (!combinations.Contains(word))
combinations.Add(word);
return;
}
// Go through every position of the word
for (int i = 0; i < word.Length; i++)
{
// Remove the character at the current position
// call this method with the String
generate(word.Substring(0, i) + word.Substring(i + 1));
}
}//
private static string[] InsertSymbol(string orig, int[] loc, string alternative, List<string> Chars)
{
List<string> CombinationsList = new List<string>();
string temp = "";
for (int i = 0; i < Chars.Count; i++)
{
temp = orig;
for (int j = 0; j < Chars[i].Length; j++)
{
string token = Chars[i];
if (alternative.IndexOf(token[j]) == loc[j])
{
temp = temp.Remove(loc[j], 1);
temp = temp.Insert(loc[j], token[j].ToString());
// int pos = sourceSubst.IndexOf(token[j]);
// sourceSubst = sourceSubst.Remove(pos, 1);
// sourceSubst = sourceSubst.Insert(pos, ".");
}
else
{
temp = temp.Remove(alternative.IndexOf(token[j]), 1);
temp = temp.Insert(alternative.IndexOf(token[j]), token[j].ToString());
}
}
CombinationsList.Add(temp);
}
return CombinationsList.ToArray();
}//
It does sound like homework. As a suggestion, I would ignore the first parameter and focus on getting all possible permutations of the second string. What's turned off, what's turned on, etc. From that list, you can easily come up with a method of swapping out characters of the first string.
On that note, I'm in the uncomfortable position of having a function ready to go but not wanting to post it because of the homework implication. I'd sure love for somebody to review it, though! And technically, there's two functions involved because I just happened to already have a generic function to generate subsets lying around.
Edit: OP says it isn't homework, so here is what I came up with. It has been refactored a bit since the claim of two functions, and I'm more than open to criticism.
using System;
using System.Collections.Generic;
using System.Text;
class Program
{
static void Main()
{
string original = "phenomenal";
string pattern = "*xo**q*t**";
string[] replacements = StringUtility.GetReplacementStrings(original, pattern, true);
foreach (string replacement in replacements)
Console.WriteLine(replacement);
Console.Read();
}
public static class StringUtility
{
public static string[] GetReplacementStrings(string original, string pattern, bool includeOriginal)
{
// pattern and original might not be same length
int maxIndex = Math.Max(original.Length, pattern.Length);
List<int> positions = GetPatternPositions(pattern, maxIndex, '*');
List<int[]> subsets = ArrayUtility.CreateSubsets(positions.ToArray());
List<string> replacements = GenerateReplacements(original, pattern, subsets);
if (includeOriginal)
replacements.Insert(0, original);
return replacements.ToArray();
}
private static List<string> GenerateReplacements(string original, string pattern, List<int[]> subsets)
{
List<string> replacements = new List<string>();
char[] temp = new char[original.Length];
foreach (int[] subset in subsets)
{
original.CopyTo(0, temp, 0, original.Length);
foreach (int index in subset)
{
temp[index] = pattern[index];
}
replacements.Add(new string(temp));
}
return replacements;
}
private static List<int> GetPatternPositions(string pattern, int maxIndex, char excludeCharacter)
{
List<int> positions = new List<int>();
for (int i = 0; i < maxIndex; i++)
{
if (pattern[i] != excludeCharacter)
positions.Add(i);
}
return positions;
}
}
public static class ArrayUtility
{
public static List<T[]> CreateSubsets<T>(T[] originalArray)
{
List<T[]> subsets = new List<T[]>();
for (int i = 0; i < originalArray.Length; i++)
{
int subsetCount = subsets.Count;
subsets.Add(new T[] { originalArray[i] });
for (int j = 0; j < subsetCount; j++)
{
T[] newSubset = new T[subsets[j].Length + 1];
subsets[j].CopyTo(newSubset, 0);
newSubset[newSubset.Length - 1] = originalArray[i];
subsets.Add(newSubset);
}
}
return subsets;
}
}
}
since it's hopw work I'd only suggest some way to solve the problem rather than writing the code.
if you loop the second parameter every time you hit a letter you'll have to options either use the letter from the first argument or the letter from the second. collect all these optins together with the index. keep a list of the parts from the first argument that will never change. iterate thorugh those two lists to created all the possible permutations
Decimal to Binary converted code is stolon copied from here.
static void Main()
{
string string1 = "basement";
string string2 = "**a*f**a";
string[] result = GetCombinations(string1, string2);
foreach (var item in result)
{
Console.WriteLine(item);
}
}
private static string[] GetCombinations(string string1, string string2)
{
var list = new List<List<char>> { new List<char>(), new List<char>() };
var cl = new List<char>();
List<string> result = new List<string>();
for (int i = 0; i < string1.Length; i++)
{
if (string2[i] == '*')
{
cl.Add(string1[i]);
}
else
{
list[0].Add(string1[i]);
list[1].Add(string2[i]);
}
}
int l = list[0].Count;
for (int i = 0; i < (Int64)Math.Pow(2.0,l); i++)
{
string s = ToBinary(i, l);
string ss = "";
int x = 0;
int y = 0;
for (int I = 0; I < string1.Length; I++)
{
if (string2[I] == '*')
{
ss += cl[x].ToString();
x++;
}
else
{
ss += (list[int.Parse(s[y].ToString())][y]);
y++;
}
}
result.Add(ss);
}
return result.ToArray<string>();
}
public static string ToBinary(Int64 Decimal, int width)
{
Int64 BinaryHolder;
char[] BinaryArray;
string BinaryResult = "";
while (Decimal > 0)
{
BinaryHolder = Decimal % 2;
BinaryResult += BinaryHolder;
Decimal = Decimal / 2;
}
BinaryArray = BinaryResult.ToCharArray();
Array.Reverse(BinaryArray);
BinaryResult = new string(BinaryArray);
var d = width - BinaryResult.Length;
if (d != 0) for (int i = 0; i < d; i++) BinaryResult = "0" + BinaryResult;
return BinaryResult;
}
which password cracker do you want to program? :)
how about
if string2 contains '*'
foreach(char ch in string1)
replace first * with ch,
execute FunctionName
else
print string2

Categories

Resources