How to get the specific sub-string position in a string - c#

I have a string 121712 1512 0025 64559 7259181568 701 013 2.Now as per my requirement i have to get the last sub-string 2 StartIndex and EndIndex .But here the issue is with the point that 2 is coming in the first substring 121712 so it is taking from there which i dont want ..
Here is the code that i have tried..
string s = "121712 1512 0025 64559 7259181568 701 013 2 ";
string inout = "2";
string[] arrs = s.Split(' ');
for (int i = 0; i <= arrs.Length; i++)
{
string str = arrs[i];
if (str == inout)
{
int startIndex = s.IndexOf(arrs[i]);
int endIndex = s.IndexOf(" ", startIndex);
int difference = endIndex - startIndex;
string inoutSubstring = (startIndex + "," + difference);
}
}
Please help me to resolve the issue ..Thanks.

You said last substring Right??
s.LastIndexOf(inout) will give the starting index of Inout string. Now I need to get endindex of Inout in s string. add inout.Lenght-1 into s.LastIndexOf(inout) that will give Last index of inout string.
You can do for any string just assign new sting int inout variable like of "21" , "12" or many other.
string inout = "2";
int startIndex;
int endIndex;
startIndex = s.LastIndexOf(inout);
endIndex = startIndex + inout.Length-1;

If I understand you correctly, you want to find the last incidence of a substring within a string. The String object in C# has a method designed for exactly this, String.LastIndexOf:
string s = "121712 1512 0025 64559 7259181568 701 013 2 ";
string inout = "2";
string[] arrs = s.Split(' ');
for (int i = 0; i <= arrs.Length; i++)
{
string str = arrs[i];
if (str == inout)
{
int startIndex = s.IndexOf("2");
int endIndex = s.LastIndexOf("2");
}
}
Note that both of these methods will return -1 if they can't find an incidence of the substring. Additionally, if there's only a single incidence of a substring, they'll both return the same value.

Related

How to split string by number of characters and add at the begin of each string custom string

For example I have some string, length of this string = 2900
How can I divide this string by parts(length 255) and add for each part "Part {number}" + dividing string
On input: string (2900 length)
Output: List with 12 element and each element should be = Part {number} + substring and length less than 255
I try smth like that, but I have trouble when I have more than 9 part
public static IEnumerable<string> SplitJobComment(string str, int chunkLength)
{
var partNumber = 1;
var partNumberTemplate = $"Part {partNumber} ";
chunkLength -= partNumberTemplate.Length;
for (var i = 0; i < str.Length; i += chunkLength)
{
if (chunkLength + i > str.Length)
{
chunkLength = str.Length - i;
}
partNumberTemplate = $"Part {partNumber} ";
partNumber++;
yield return partNumberTemplate + str.Substring(i, chunkLength);
}
}
Given that the real problem, as I assumed, is the fact that partNumberTemplate's length changes when partNumber>9, one possibile solution can be
var partNumberTemplate = $"Part {partNumber:D2} ";
{partNumber:D2} formats the number using always 2 digits.

Finding the longest word (and write it out) in string without split, distinct and foreach [duplicate]

This question already has answers here:
Finding longest word in string
(4 answers)
Closed 3 years ago.
I got an assignment to make a method to find the longest word in a string without split, distinct and foreach.
I was able to split the words and count the length but I am stuck on how can I actually compare and write them out.
static void Main(string[] args)
{
String s1 = "Alex has 2 hands.";
longestWord(s1);
Console.
}
static void longestWord(String s1)
{
char emp = ' ';
int count = 0;
char[] ee = s1.ToCharArray();
for (int i = 0; i < ee.Length; i++)
{
if (ee[i] == emp || ee[i] == '.')
{
count++;
Console.Write(" " + (count-1));
Console.WriteLine();
count = 0;
}
else
{
Console.Write(ee[i]);
count++;
}
}
}
The output right now looks like this:
Alex 4
has 3
2 1
hands 5
I am pretty sure I would be able to get only the longest number to show by comparing count before reset with temp int but how to write out the word with it.
Or if there is a easier way which probably is.
You are already on a good way. Instead of directly printing the words, store the length and position of the longest word and print it at the end. Like so:
static void longestWord(String s1)
{
char emp = ' ';
int longestLength = 0;
int longestStart = 0;
int currentStart = 0;
for (int i = 0; i < s1.Length; i++)
{
if (s1[i] == emp || s1[i] == '.')
{
// calculate the current word length
int currentLength = i - currentStart;
// test if this is longer than the currently longest
if(currentLength > longestLength)
{
longestLength = currentLength;
longestStart = currentStart;
}
// a new word starts at the next character
currentStart = i + 1;
}
}
// print the longest word
Console.WriteLine($"Longest word has length {longestLength}: \"{s1.Substring(longestStart, longestLength)}\"");
}
There is no need for the .ToCharArray(). You can access the string directly.
I will question whether you are actually supposed to treat "2" as a word and count it at all. Using regular expressions will allow you to approach the problem using a LINQ one-liner:
static void Main(string[] args)
{
String s1 = "Alex has 2 hands.";
var word = longestWord(s1);
Console.WriteLine(word);
//Console.ReadLine();
}
static string longestWord(string s1) {
return Regex.Matches(s1,"[A-Za-z]+") // find all sequences containing alphabetical characters, you can add numberas as well: [A-Za-z0-9]
.Cast<Match>() // cast results to Enumberable<Match> so we can apply LINQ to it
.OrderByDescending(m => m.Length) // luckily for us, Match comes with Length, so we just sort our results by it
.Select(m => m.Value) // instead of picking up everything, we only want the actual word
.First(); // since we ordered by descending - first item will be the longest word
}
You can store for every word the chars in new list of chars (list for dynamic length)
and if the new word is longer of the prev long word convert it to string.
If you have two word in same length it will take the first.
If you want the last change the "maxLength < count" to "maxLength <= count"
static string longestWord(String s1)
{
char emp = ' ';
int count = 0;
int maxLength = 0;
string maxWord = string.Empty;
List<char> newWord = new List<char>();
char[] ee = s1.ToCharArray();
for (int i = 0; i < ee.Length; i++)
{
if (ee[i] == emp || ee[i] == '.')
{
if (maxLength < count)
{
maxLength = count;
maxWord = new string(newWord.ToArray());
}
count = 0;
newWord = new List<char>();
}
else
{
newWord.Add(ee[i]);
count++;
}
}
return maxWord;
}

Find all possible combinations of word with and without hyphens

For a string that may have zero or more hyphens in it, I need to extract all the different possibilities with and without hyphens.
For example, the string "A-B" would result in "A-B" and "AB" (two possibilities).
The string "A-B-C" would result in "A-B-C", "AB-C", "A-BC" and "ABC" (four possibilities).
The string "A-B-C-D" would result in "A-B-C-D", "AB-C-D", "A-BC-D", "A-B-CD", "AB-CD", "ABC-D", "A-BCD" and "ABCD" (eight possibilities).
...etc, etc.
I've experimented with some nested loops but haven't been able to get anywhere near the desired result. I suspect I need something recursive unless there is some simple solution I am overlooking.
NB. This is to build a SQL query (shame that SQL Server does't have MySQL's REGEXP pattern matching).
Here is one attempt I was working on. This might work if I do this recursively.
string keyword = "A-B-C-D";
List<int> hyphens = new List<int>();
int pos = keyword.IndexOf('-');
while (pos != -1)
{
hyphens.Add(pos);
pos = keyword.IndexOf('-', pos + 1);
}
for (int i = 0; i < hyphens.Count(); i++)
{
string result = keyword.Substring(0, hyphens[i]) + keyword.Substring(hyphens[i] + 1);
Response.Write("<p>" + result);
}
A B C D are words of varying length.
Take a look at your sample cases. Have you noticed a pattern?
With 1 hyphen there are 2 possibilities.
With 2 hyphens there are 4 possibilities.
With 3 hyphens there are 8 possibilities.
The number of possibilities is 2n.
This is literally exponential growth, so if there are too many hyphens in the string, it will quickly become infeasible to print them all. (With just 30 hyphens there are over a billion combinations!)
That said, for smaller numbers of hyphens it might be interesting to generate a list. To do this, you can think of each hyphen as a bit in a binary number. If the bit is 1, the hyphen is present, otherwise it is not. So this suggests a fairly straightforward solution:
Split the original string on the hyphens
Let n = the number of hyphens
Count from 2n - 1 down to 0. Treat this counter as a bitmask.
For each count begin building a string starting with the first part.
Concatenate each of the remaining parts to the string in order, preceded by a hyphen only if the corresponding bit in the bitmask is set.
Add the resulting string to the output and continue until the counter is exhausted.
Translated to code we have:
public static IEnumerable<string> EnumerateHyphenatedStrings(string s)
{
string[] parts = s.Split('-');
int n = parts.Length - 1;
if (n > 30) throw new Exception("too many hyphens");
for (int m = (1 << n) - 1; m >= 0; m--)
{
StringBuilder sb = new StringBuilder(parts[0]);
for (int i = 1; i <= n; i++)
{
if ((m & (1 << (i - 1))) > 0) sb.Append('-');
sb.Append(parts[i]);
}
yield return sb.ToString();
}
}
Fiddle: https://dotnetfiddle.net/ne3N8f
You should be able to track each hyphen position, and basically say its either there or not there. Loop through all the combinations, and you got all your strings. I found the easiest way to track it was using a binary, since its easy to add those with Convert.ToInt32
I came up with this:
string keyword = "A-B-C-D";
string[] keywordSplit = keyword.Split('-');
int combinations = Convert.ToInt32(Math.Pow(2.0, keywordSplit.Length - 1.0));
List<string> results = new List<string>();
for (int j = 0; j < combinations; j++)
{
string result = "";
string hyphenAdded = Convert.ToString(j, 2).PadLeft(keywordSplit.Length - 1, '0');
// Generate string
for (int i = 0; i < keywordSplit.Length; i++)
{
result += keywordSplit[i] +
((i < keywordSplit.Length - 1) && (hyphenAdded[i].Equals('1')) ? "-" : "");
}
results.Add(result);
}
This works for me:
Func<IEnumerable<string>, IEnumerable<string>> expand = null;
expand = xs =>
{
if (xs != null && xs.Any())
{
var head = xs.First();
if (xs.Skip(1).Any())
{
return expand(xs.Skip(1)).SelectMany(tail => new []
{
head + tail,
head + "-" + tail
});
}
else
{
return new [] { head };
}
}
else
{
return Enumerable.Empty<string>();
}
};
var keyword = "A-B-C-D";
var parts = keyword.Split('-');
var results = expand(parts);
I get:
ABCD
A-BCD
AB-CD
A-B-CD
ABC-D
A-BC-D
AB-C-D
A-B-C-D
I've tested this code and it is working as specified in the question. I stored the strings in a List<string>.
string str = "AB-C-D-EF-G-HI";
string[] splitted = str.Split('-');
List<string> finalList = new List<string>();
string temp = "";
for (int i = 0; i < splitted.Length; i++)
{
temp += splitted[i];
}
finalList.Add(temp);
temp = "";
for (int diff = 0; diff < splitted.Length-1; diff++)
{
for (int start = 1, limit = start + diff; limit < splitted.Length; start++, limit++)
{
int i = 0;
while (i < start)
{
temp += splitted[i++];
}
while (i <= limit)
{
temp += "-";
temp += splitted[i++];
}
while (i < splitted.Length)
{
temp += splitted[i++];
}
finalList.Add(temp);
temp = "";
}
}
I'm not sure your question is entirely well defined (i.e. could you have something like A-BCD-EF-G-H?). For "fully" hyphenated strings (A-B-C-D-...-Z), something like this should do:
string toParse = "A-B-C-D";
char[] toParseChars = toPase.toCharArray();
string result = "";
string binary;
for(int i = 0; i < (int)Math.pow(2, toParse.Length/2); i++) { // Number of subsets of an n-elt set is 2^n
binary = Convert.ToString(i, 2);
while (binary.Length < toParse.Length/2) {
binary = "0" + binary;
}
char[] binChars = binary.ToCharArray();
for (int k = 0; k < binChars.Length; k++) {
result += toParseChars[k*2].ToString();
if (binChars[k] == '1') {
result += "-";
}
}
result += toParseChars[toParseChars.Length-1];
Console.WriteLine(result);
}
The idea here is that we want to create a binary word for each possible hyphen. So, if we have A-B-C-D (three hyphens), we create binary words 000, 001, 010, 011, 100, 101, 110, and 111. Note that if we have n hyphens, we need 2^n binary words.
Then each word maps to the output you desire by inserting the hyphen where we have a '1' in our word (000 -> ABCD, 001 -> ABC-D, 010 -> AB-CD, etc). I didn't test the code above, but this is at least one way to solve the problem for fully hyphenated words.
Disclaimer: I didn't actually test the code

Increase string array value +1?

How would I increase the value of this array +1?
I have some code but its not getting +1 the value of that array.
By +1 I mean the array value 1 above that one, so if my array contains the words: Hi, Hey Hello, instead of it displaying Hi I want it so display Hey.
Heres the code I have but its not moving it +1 up:
string[] u = getBetweenAll(vid, "</id><published>", "</published><updated>");
for (int i = 0; i < listView1.Items.Count; i++)
{
string input = u[i] + 1;
int index = input.IndexOf("T");
if (index > 0)
input = input.Substring(0, index);
listView1.Items[i].SubItems.Add(input);
}
Did you mean:
string input = u[i + 1];
string input = u[i + 1];
you need to increment the indexer

Mask out part first 12 characters of string with *?

How can I take the value 123456789012345 or 1234567890123456 and turn it into:
************2345 and ************3456
The difference between the strings above is that one contains 15 digits and the other contains 16.
I have tried the following, but it does not keep the last 4 digits of the 15 digit number and now matter what the length of the string, be it 13, 14, 15, or 16, I want to mask all beginning digits with a *, but keep the last 4. Here is what I have tried:
String.Format("{0}{1}", "************", str.Substring(11, str.Length - 12))
Something like this:
string s = "1234567890123"; // example
string result = s.Substring(s.Length - 4).PadLeft(s.Length, '*');
This will mask all but the last four characters of the string. It assumes that the source string is at least 4 characters long.
using System;
class Program
{
static void Main()
{
var str = "1234567890123456";
if (str.Length > 4)
{
Console.WriteLine(
string.Concat(
"".PadLeft(12, '*'),
str.Substring(str.Length - 4)
)
);
}
else
{
Console.WriteLine(str);
}
}
}
Easiest way: Create an extension method to extract the last four digits. Use that in your String.Format call.
For example:
public static string LastFour(this string value)
{
if (string.IsNullOrEmpty(value) || value.length < 4)
{
return "0000";
}
return value.Substring(value.Length - 4, 4)
}
In your code:
String.Format("{0}{1}", "************", str.LastFour());
In my opinion, this leads to more readable code, and it's reusable.
EDIT: Perhaps not the easiest way, but an alternative way that may produce more maintainable results. <shrug/>
Try this:
var maskSize = ccDigits.Length - 4;
var mask = new string('*', maskSize) + ccDigits.Substring(maskSize);
LINQ:
char maskBy = '*';
string input = "123456789012345";
int count = input.Length <= 4 ? 0 : input.Length - 4;
string output = new string(input.Select((c, i) => i < count ? maskBy : c).ToArray());
static private String MaskInput(String input, int charactersToShowAtEnd)
{
if (input.Length < charactersToShowAtEnd)
{
charactersToShowAtEnd = input.Length;
}
String endCharacters = input.Substring(input.Length - charactersToShowAtEnd);
return String.Format(
"{0}{1}",
"".PadLeft(input.Length - charactersToShowAtEnd, '*'),
endCharacters
);
}
Adjust the function header as required, call with:
MaskInput("yourInputHere", 4);
private string MaskDigits(string input)
{
//take first 6 characters
string firstPart = input.Substring(0, 6);
//take last 4 characters
int len = input.Length;
string lastPart = input.Substring(len - 4, 4);
//take the middle part (****)
int middlePartLenght = len - (firstPart.Length + lastPart.Length);
string middlePart = new String('*', middlePartLenght);
return firstPart + middlePart + lastPart;
}
MaskDigits("1234567890123456");
// output : "123456******3456"
Try the following:
private string MaskString(string s)
{
int NUM_ASTERISKS = 4;
if (s.Length < NUM_ASTERISKS) return s;
int asterisks = s.Length - NUM_ASTERISKS;
string result = new string('*', asterisks);
result += s.Substring(s.Length - NUM_ASTERISKS);
return result;
}
Regex with a match evaluator will do the job
string filterCC(string source) {
var x=new Regex(#"^\d+(?=\d{4}$)");
return x.Replace(source,match => new String('*',match.Value.Length));
}
This will match any number of digits followed by 4 digits and the end (it won't include the 4 digits in the replace). The replace function will replace the match with a string of * of equal length.
This has the additional benefit that you could use it as a validation algorthim too. Change the first + to {11,12} to make it match a total of 15 or 16 chars and then you can use x.IsMatch to determine validity.
EDIT
Alternatively if you always want a 16 char result just use
return x.Replace(source,new String('*',12));
// "123456789".MaskFront results in "****56789"
public static string MaskFront(this string str, int len, char c)
{
var strArray = str.ToCharArray();
for (var i = 0; i < len; i++)
{
if(i < strArray.Length)
{
strArray[i] = c;
}
else
{
break;
}
}
return string.Join("", strArray);
}
// "123456789".MaskBack results in "12345****"
public static string MaskBack(this string str, int len, char c)
{
var strArray = str.ToCharArray();
var tracker = strArray.Length - 1;
for (var i = 0; i < len; i++)
{
if (tracker > -1)
{
strArray[tracker] = c;
tracker--;
}
else
{
break;
}
}
return string.Join("", strArray);
}
Try this out:
static string Mask(string str)
{
if (str.Length <= 4) return str;
Regex rgx = new Regex(#"(.*?)(\d{4})$");
string result = String.Empty;
if (rgx.IsMatch(str))
{
for (int i = 0; i < rgx.Matches(str)[0].Groups[1].Length; i++)
result += "*";
result += rgx.Matches(str)[0].Groups[2];
return result;
}
return str;
}
Mask from start and from end with sending char
public static string Maskwith(this string value, int fromStart, int fromEnd, char ch)
{
return (value?.Length >= fromStart + fromEnd) ?
string.Concat(Enumerable.Repeat(ch, fromStart)) + value.Substring(fromStart, value.Length - (fromStart + fromEnd)) + string.Concat(Enumerable.Repeat(ch, fromEnd))
: "";
} //Console.WriteLine("mytestmask".Maskwith(2,3,'*')); **testm***
show chars from start and from end by passing value and mask the middle
public static string MasktheMiddle(this string value, int visibleCharLength, char ch)
{
if (value?.Length <= (visibleCharLength * 2))
return string.Concat(Enumerable.Repeat(ch,value.Length));
else
return value.Substring(0, visibleCharLength) + string.Concat(Enumerable.Repeat(ch, value.Length - (visibleCharLength * 2))) + value.Substring(value.Length - visibleCharLength);
} //Console.WriteLine("mytestmask".MasktheMiddle(2,'*')); Result: my******sk
How can I take the value 123456789012345 or 1234567890123456 and turn it into:
************2345 and ************3456
one more way to do this:
var result = new string('*',0,value.Length - 4) + new string(value.Skip(value.Length - 4).ToArray())
// or using string.Join
An extension method using C# 8's index and range:
public static string MaskStart(this string input, int showNumChars, char maskChar = '*') =>
input[^Math.Min(input.Length, showNumChars)..]
.PadLeft(input.Length, maskChar);
A simple way
string s = "1234567890123"; // example
int l = s.Length;
s = s.Substring(l - 4);
string r = new string('*', l);
r = r + s;

Categories

Resources