So I actually have most of the code thought up myself and got it working last week, but just now I accidentally deleted it so here I am re-writing!
The logic goes, I have a TIN number for input, I want to split this every 3rd digit to neatly fit a physical form I have prepared. To do this, I iterate through the input, modulus by 3, place my delimiter a space, then split it by the delimiter.
So, the following 1234567891012 becomes 123 456 789 1012.
string input = txtTIN.Text;
string digit1 = "0";
string digit2 = "0";
string digit3 = "0";
string digit4 = "0";
StringBuilder sb = new StringBuilder();
for (int i = 1; i < input.Length; i++)
{
if (i%3 == 0)
{
sb.Append(' ');
sb.Append(input[i]);
}
}
string formatted = sb.ToString();
Console.WriteLine(formatted);
string[] formatCollection = formatted.Split(' ');
digit1 = formatCollection[0];
digit2 = formatCollection[1];
digit3 = formatCollection[2];
digit4 = formatCollection[3];
I realize now that I post it here that there seems to be something wrong with the string building, as a Console write is returning 1 4 7 out of the input. Not a desired result, but if I remember correctly, all of the pieces are already in place.
(Note, I do not want to use Linq, Regex, or Lists even though I know they are better alternatives. I thought this one up myself and want to see it work in the end.)
Also, how do I make it so that an input of 123456789101251 becomes 123 456 789 101251, in other words, i do not want to split any further than the first 3, something my current code fails to do.
There are couple of issues with your code
You start your iteration with 1, not 0.
You add a space at the beginning of your result.
You are only adding the first characters of each group.
You don't stop grouping even when your max amount of groups is reached.
This would address your issues:
const int GROUP_LENGTH = 3;
const int GROUP_COUNT = 3;
const int MAX_GROUPED_LENGTH = GROUP_LENGTH * GROUP_COUNT;
int groupedLength = Math.Min(input.Length, MAX_GROUPED_LENGTH);
for (int i = 0; i < groupedLength; i++)
{
if ((i > 0) && ((i % GROUP_LENGTH) == 0))
{
sb.Append(' ');
}
sb.Append(input[i]);
}
if (input.Length > MAX_GROUPED_LENGTH)
{
sb.Append(' ');
sb.Append(input, MAX_GROUPED_LENGTH, input.Length - MAX_GROUPED_LENGTH);
}
int size = 3; //size of the chunk
int count = 3; //how many sized chunks will be splitted
int length = input.Length / size;
int iterate = length < count ? length : count;
int tailLength = input.Length - iterate * size;
for (int i = 0; i < iterate; i++)
{
sb.Append(input.Substring(i, size));
sb.Append(' ');
}
if (tailLength > 0)
{
sb.Append(input.Substring(size * iterate, tailLength));
}
The code to add the digits int he string is in the wrong place. You are only adding the number to the string if it is index mod 3 is 0
for (int i = 1; i < input.Length; i++)
{
sb.Append(input[i]);
if (i%3 == 0)
{
sb.Append(' ');
}
}
string[] result = new string[4];
int groups = input.Length / 3;
if (groups > 3) groups = 3;
int group;
for (group = 0; group < groups; group++)
{
result[group] = input.Substring(group*3, 3);
}
// Assert: group < 4
result[group] = input.Substring(group*3);
// Assert: answers in result[0..groupCount-1]
int groupCount = group+1;
If you really don't want to use LINQ, i would propose to modify your algorithm this way:
StringBuilder sb = new StringBuilder();
StringBuilder partBuilder = new StringBuilder();
int partsSplitted = 0;
for (int i = 1; i <= input.Length; i++)
{
partBuilder.Append(input[i-1]);
if (i % 3 == 0 && partsSplitted<=3)
{
sb.Append(' ');
sb.Append(partBuilder.ToString());
partBuilder = new StringBuilder();
partsSplitted++;
}
}
sb.Append(partBuilder.ToString());
string formatted = sb.ToString().TrimStart();
With output:
123 456 789 101251
The changed to your idea are minimal and entire loop is the same. Please notify: your for loop should go till i <= input.Length not i < input.Length because you are starting with index 1, not 0.
Could downvoters explain what is wrong with accepted answer?
Related
I need split my string in 2, one letter to each variable.
Example: string = "ABCDEFGHIJ"
name1: ACEGI
name2: BDFHJ
I done so far:
var builderM = new StringBuilder();
var builderK = new StringBuilder();
for (int i = 0; i < s.Length; i++)
{
builderM.Append(s[i]);
builderK.Append(s[i++]);
}
txtM.Text = builderM.ToString();
txtK.Text = builderK.ToString();
But its showing same text in the 2.
you should use ++i instead of i++
for (int i = 0; i < s.Length; i++)
{
builderM.Append(s[i]);
if(i + 1 < s.Length) // to prevent IOR exception when count is odd.
builderK.Append(s[++i]); // pre increment.
}
the reason is that i++ is post incremented. that means i gets incremented after the expression therefor s[i++] will give you same item as s[i].
Another approach would be to use LINQ to filter odd and even indices into two strings, something like:
var even = new string(input.Where((c, idx) => idx % 2 == 0).ToArray());
var odd = new string(input.Where((c, idx) => idx % 2 != 0).ToArray());
If performance is not an issue, you can use LINQ:
var name1 = String.Join(String.Empty, str.Where((v, i) => i % 2 == 0));
var name2 = String.Join(String.Empty, str.Where((v, i) => i % 2 == 1));
You can also use the modulus operator (%) to determine if the index is even or odd, and put the even indexes in the first array and the odd indexes in the second one:
for (int i = 0; i < s.Length; i++)
{
if (i % 2 == 0) builderM.Append(s[i]);
else builderK.Append(s[i]);
}
If you'd rather increment the i inside the for body, you have to repeat the check against s.Length (as we do in the for condition). Also, you will need to either move the post-increment to the previous line (so that i is incremented in time), or use a pre-increment:
// Move post-increment to previous line example:
for (int i = 0; i < s.Length; i++)
{
builderM.Append(s[i++]);
if (i < s.Length) builderK.Append(s[i]);
}
// Use a pre-increment example:
for (int i = 0; i < s.Length; i++)
{
builderM.Append(s[i]);
if (++i < s.Length) builderK.Append(s[i]);
}
I've seen few implementations of variations of string in C#, but none of them had any limitation on their length. Unfortunately, I cannot modify them to achieve my goal which is e.g.
for:
string = "ABCD" and variationLength = 2
generate new strings:
AB, AC, AD, BA, BC, BD, CA, CB, CD, DA, DB, DC
I'm looking for exactly this Python's itertools.permutations implementation but in C#. (https://docs.python.org/3/library/itertools.html#itertools.permutations)
Is there anything similar to its in C#? If not, then what is the easiest way to implement it?
Edit_2:
so far I came up with an idea to list all unique chars of given string and then get variations out of them
static void PrintAllKLengthPerm(string str, int k)
{
int n = str.Length;
PrintAllKLengthPermRec(str, "", n, k);
}
// The main recursive method to print all possible strings of length k
static void PrintAllKLengthPermRec(string str, String prefix, int n, int k)
{
// Base case: k is 0, print prefix
if (k == 0)
{
Console.WriteLine(prefix);
return;
}
// One by one add all characters from str and recursively
// call for k equals to k-1
for (int i = 0; i < n; ++i)
{
// Next character of input added
String newPrefix = prefix + str[i];
// k is decreased, because we have added a new character
PrintAllKLengthPermRec(str, newPrefix, n, k - 1);
}
}
static void Main(string[] args)
{
string str = "ABCD";
int permLen = 2;
//get all unique characters in string
string uniqStr = new String(str.Distinct().ToArray());
// Print all possible strings of length permLen out of uniqStr characters
PrintAllKLengthPerm(uniqStr, permLen);
}
However I am looking for more optimal and effective solution
Here's a truly recursive permutation method:
public IEnumerable<string> Permutate(string source, int count)
{
if (source.Length == 1)
{
yield return source;
}
else if (count == 1)
{
for (var n = 0; n < source.Length; n++)
{
yield return source.Substring(n, 1);
}
}
else
{
for (var n = 0; n < source.Length; n++)
foreach (var suffix in Permutate(
source.Substring(0, n)
+ source.Substring(n + 1, source.Length - n - 1), count -1))
{
yield return source.Substring(n, 1) + suffix;
}
}
}
It can be called with Permutate("ABCD", 2) and returns this:
I made the following recursive function which accomplishes your task:
static void Permutations(List<string> output, string str, int n, string curr)
{
if(curr.Length == n)
{
output.Add(curr);
return;
}
foreach(char c in str)
if(!curr.Contains(c.ToString()))
Permutations(output, str, n, curr + c.ToString());
}
and then you call it like this:
string str = "ABCD";
int length = 2;
List<string> perms = new List<string>();
Permutations(perms, str, length, "");
// now the list "perms" will contain the permutations of "str" in length "n"
List<string> newPermutations = new List<string>();
for(int a = 0; a!=inString.Count; a++)
for((int b = 0; b!=inString.Count; b++)
if(noRepetitions && a == b) continue;
newPermutations.Add(""+inString[a] + inString[b]);
I think that that should work; I am still trying to figure out a way to not only have 2 letters.
Edit: Edited it to work, the old one just didn't work... lol
Edit: Thanks to #Bloopy, they helped me spot some errors in my for loops
Here's a solution using modulo and division. There are 4² possible strings of length 2 using the letters ABCD. Number them from 0 to 4²-1 and repeatedly divide each number by 4. Use the resulting remainders as array indexes on the ABCD string.
This has the advantage of allowing you to keep the strings with repeated elements (AA, BB, CC, DD) when needed – just skip the discard step.
string alphabet = "ABCD";
int length = 2;
int[] indexes = new int[length];
char[] item = new char[length];
// loop through all possible strings for the given alphabet and length
for (int i = 0; i < Math.Pow(alphabet.Length, length); i++) {
int dividend = i;
for (int j = length - 1; j >= 0; j--) {
indexes[j] = dividend % alphabet.Length;
dividend /= alphabet.Length;
}
// discard any that use the same alphabet element more than once
if (indexes.Distinct().Count() < length)
continue;
for (int k = 0; k < length; k++) {
item[k] = alphabet[indexes[k]];
}
Console.WriteLine(item);
}
Alternatively, here's a really brief solution using LINQ. Note that this one doesn't work correctly if there are duplicate elements in the string (unless you want to remove the call to Where and keep the AA, BB etc.). I'd need to track the indexes like I did in my method above.
IEnumerable<string> prm = alphabet.Select(c => c.ToString());
for (int a = 1; a < length; a++)
prm = prm.SelectMany(s => alphabet.Where(t => !s.Contains(t)), (x, y) => x + y);
foreach (string s in prm)
Console.WriteLine(s);
Inside a For loop I do not understand following behavior of string.Substring(i,j)
having the code
String line = "TTACCTTAAC";
int k = 3; //this is variable but for simplicity is 3
String _pattern = "";
for (int i = 0; i <= line.Length - k; i++) {
_pattern = line.Substring(i, i + k );
//do something...
}
I am expecting the loop to walk over string Line (TACCTTAAC) (from 0 to 10-3 = 7)like:
TTA
ACC
CCT
CTT
TTA
TAA
AAC
However I get
TTA
ACCT
etc...
What am I missing?
Second parameter of Substring is length, not end, so you should just pass k instead of doing your math:
String line = "TTACCTTAAC";
int k = 3; //this is variable but for simplicity is 3
String _pattern = "";
for (int i = 0; i <= line.Length - k; i++) {
_pattern = line.Substring(i, k);
//do something...
}
substring function in c# is used as string.Substring(int startindex, int Length)
so you should use
_pattern = line.Substring(i, k);
Is there a method that will remove a set amount of characters from a string, placing the removed characters into a separate string and leaving the original x amount of characters shorter?
I need to parse a string into 10 individual strings, each 10 characters long. I would like to be able to do sommething simple like this, but I do not know if there is a method that works like this in C#
string[] errorCodes = new string[10];
for (int i = 0; i < errorCodes.Length; i++)
{
errorCodes[i] = retrievedMessage.removeFromSubstring(0, 10);
}
You could try this:
string[] errorCodes = new string[10];
for (int i = 0; i < errorCodes.Length; i++)
{
errorCodes[i] = retrievedMessage.Substring(0, 10);
retrievedMessage = retrievedMessage.Substring(10);
}
The line retrievedMessage = retrievedMessage.Substring(10); will effectively remove the first 10 characters from the original string. This way in each iteration you will be able to use the first 10 characters and assign them to the errorCodes[i]
Also you could try to avoid using substrings:
string[] errorCodes = new string[10];
for (int i = 0; i < errorCodes.Length; i++)
{
errorCodes[i] = retrievedMessage.Substring(i*10, 10);
}
Edit
Now tested, seems to work fine for me
var errorCodes = "longstringgggggggggggggggggggggggggg";
var count = 10;
List<string> s = new List<string>();
for (int i = 0; i < errorCodes.Length; i += count)
{
if (i + count > errorCodes.Length)
count = errorCodes.Length - i;
s.Add(errorCodes.Substring(i, count));
}
foreach (var str in s)
Console.WriteLine(str);
Console.ReadLine();
This should work for you
string[] errorCodes = new string[10];
for (int i = 0; i < errorCodes.Length; i++)
{
errorCodes[i] = retrievedMessage.Substring(10*i, 10);
}
Here is an option that will remove from the string retrievedMessage
string[] errorCodes = new string[10];
for (int i = 0; i < errorCodes.Length; i++)
{
//option to remove from string
errorCodes[i] = retrievedMessage.Substring(0, 10);
retrievedMessage = retrievedMessage.Remove(0,10); //will remove from string
}
Same basic concept as other answers but with a little checking for variable string length. If you know that your string is always 100 chars in length, then use one of the simpler answers.
string[] errorCodes = new string[10];
for (int i = 0; i < errorCodes.Length; i++)
{
int startIndex = i * 10;
if (retrievedMessage.Length > startIndex)
{
int length = 10;
if (retrievedMessage.Length < (startIndex + length))
{
length = retrievedMessage.Length - startIndex;
}
errorCodes[i] = retrievedMessage.Substring(startIndex, length);
}
}
Note: Since errorCodes is always instantiated with a length of 10, this will have null strings if the length of retrievedMessage is <= 90. If you expect variable length, better to use a List<string> than a string[].
I have many strings. Each string is prepended with at least 1 $. What is the best way to loop through the chars of each string to count how many $'s there are per string.
eg:
"$hello" - 1
"$$hello" - 2
"$$h$ello" - 2
You could use the Count method
var count = mystring.Count(x => x == '$')
int count = myString.TakeWhile(c => c == '$').Count();
And without LINQ
int count = 0;
while(count < myString.Length && myString[count] == '$') count++;
The simplest approach would be to use LINQ:
var count = text.TakeWhile(c => c == '$').Count();
There are certainly more efficient approaches, but that's probably the simplest.
You could do this, it doesn't require LINQ, but it's not the best way to do it(since you make split the whole string and put it in an array and just pick the length of it, you could better just do a while loop and check every character), but it works.
int count = test.Split('$').Length - 1;
var str ="hello";
str.Where(c => c == 'l').Count() // 2
int count = yourText.Length - yourText.TrimStart('$').Length;
int count = Regex.Matches(myString,"$").Count;
public static int GetHowManyTimeOccurenceCharInString(string text, char c)
{
int count = 0;
foreach(char ch in text)
{
if(ch.Equals(c))
{
count++;
}
}
return count;
}
just a simple answer:
public static int CountChars(string myString, char myChar)
{
int count = 0;
for (int i = 0; i < myString.Length; i++)
{
if (myString[i] == myChar) ++count;
}
return count;
}
Cheers! - Rick
One approach you could take is the following method:
// Counts how many of a certain character occurs in the given string
public static int CharCountInString(char chr, string str)
{
return str.Split(chr).Length-1;
}
As per the parameters this method returns the count of a specific character within a specific string.
This method works by splitting the string into an array by the specified character and then returning the length of that array -1.
//This code worked for me
class CountOfLettersOfString
{
static void Main()
{
Console.WriteLine("Enter string to check count of letters");
string name = Console.ReadLine();
//Method1
char[] testedalphabets = new char[26];
int[] letterCount = new int[26];
int countTestesd = 0;
Console.WriteLine($"Given String is:{name}");
for (int i = 0; i < name.Length - 1; i++)
{
int countChar = 1;
bool isCharTested = false;
for (int j = 0; j < testedalphabets.Length - 1; j++)
{
if (name[i] == testedalphabets[j])
{
isCharTested = true;
break;
}
}
if (!isCharTested)
{
testedalphabets[countTestesd] = name[i];
for (int k = i + 1; k < name.Length - 1; k++)
{
if (name[i] == name[k])
{
countChar++;
}
}
letterCount[countTestesd] = countChar;
countTestesd++;
}
else
{
continue;
}
}
for (int i = 0; i < testedalphabets.Length - 1; i++)
{
if (!char.IsLetter(testedalphabets[i]))
{
continue;
}
Console.WriteLine($"{testedalphabets[i]}-{letterCount[i]}");
}
//Method2
var g = from c in name.ToLower().ToCharArray() // make sure that L and l are the same eg
group c by c into m
select new { Key = m.Key, Count = m.Count() };
foreach (var item in g)
{
Console.WriteLine(string.Format("Character:{0} Appears {1} times", item.Key.ToString(), item.Count));
}
Console.ReadLine();
}
}
This is a similar Solution to find how many email addresses included in a string. This way is more efficient`
int count = 0;
foreach (char c in email.Trim())
if (c == '#') count++;