How to count white space in a string based on other string - c#

Suppose we have two string s1 and s2
s1 = "123 456 789 012 1234";
s2 = "1234567";
I want to print s2 with white space as given in string s1 . Output will be
Output = "123 456 7";

Approach with simple for loop
string s1 = "123 456 789 012 1234";
string s2 = "1234567";
for (int i = 0; i < s1.Length && i < s2.Length; i++)
{
if (char.IsWhiteSpace(s1[i]))
{
s2 = s2.Insert(i, s1[i].ToString());
}
}
https://dotnetfiddle.net/POn5E2

You should create a loop for s2 if the character equals s1 then add character to the result. Otherwise,until there add a space to result...
string s1 = "123 456 789 012 1234";
string s2 = "1234567";
string result = "";
int s1_index = 0;
for (int i = 0; i < s2.Length; i++)
{
if (s1[s1_index] == ' ')
while (s1[s1_index] == ' ')
{
result += ' ';
s1_index++;
}
if (s2[i] == s1[s1_index])
result += s1[s1_index];
s1_index++;
}
Console.WriteLine(result);

Simply just put a condition on number of non-whitespace characters. Not efficient solution, but it has a good idea:
string s1 = "123 456 789 012 1234";
string s2 = "1234567";
var s2Length = s2.Length;
var array = s1.TakeWhile((c, index) => s1.Substring(0, index + 1)
.Count(f => !char.IsWhiteSpace(f)) <= s2Length)
.ToArray();
var result = new string(array); //123 456 7

Related

Find out if a list of strings contains permutations of words from another string (counter for each combination)

I didn't know exactly how to ask this question better so I will try to explain it as best as I can.
Let's say I have one list of 20 strings myList1<string> and I have another string string ToCompare. Now each of the strings in the list as well as the string ToCompare have 8 words divided by empty spaces. I want to know how many times combination of any three words from string ToCompare in any possible order is to be found in the strings of myList1<string>. For an example:
This is the list (short version - example):
string1 = "AA BB CC DD EE FF GG HH";
string2 = "BB DD EE AA HH II JJ MM";
.......
string20 = "NN OO AA RR EE BB FF KK";
string ToCompare = "BB GG AA FF CC MM RR II";
Now I want to know how many times any combination of 3 words from ToCompare string is to be found in myList1<string>. To clarify futher three words from ToCompare "BB AA CC" are found in string1 of the list thus the counter for these 3 words would be 1. Another 3 words from ToCompare "BB AA II" are found in the string2 of myList1<string> but the counter here would be also 1 because it's not the same combination of words (I have "AA" and "BB" but also "II". They are not equal). Order of these 3 words doesn't matter, that means "AA BB CC" = "BB AA CC" = "CC BB AA". I want to know how many combinations of all (any) 3 words from ToCompare are found in myList1<string>. I hope it's clear what I mean.
Any help would be appreciated, I don't have a clue how to solve this. Thanks.
Example from Vanest:
List<string> source = new List<string>();
source.Add("2 4 6 8 10 12 14 99");
source.Add("16 18 20 22 24 26 28 102");
source.Add("33 6 97 38 50 34 87 88");
string ToCompare = "2 4 6 15 20 22 28 44";
The rest of the code is exacty the same, and the result:
Key = 2 4 6, Value = 2
Key = 2 4 20, Value = 1
Key = 2 4 22, Value = 1
Key = 2 4 28, Value = 1
Key = 2 6 20, Value = 1
Key = 2 6 22, Value = 1
Key = 2 6 28, Value = 1
Key = 2 20 22, Value = 1
Key = 2 20 28, Value = 1
Key = 2 22 28, Value = 1
Key = 4 6 20, Value = 1
Key = 4 6 22, Value = 1
Key = 4 6 28, Value = 1
Key = 4 20 22, Value = 1
Key = 4 20 28, Value = 1
Key = 4 22 28, Value = 1
Key = 6 20 22, Value = 1
Key = 6 20 28, Value = 1
Key = 6 22 28, Value = 1
Key = 20 22 28, Value = 1
As you can see there are combinations which not exist in the strings, and the value of the first combination is 2 but it comes only one time in the first string
I think this should suffice your ask,
List<string> source = new List<string>();
source.Add("AA BB CC DD EE FF GG HH");
source.Add("BB DD EE AA HH II JJ MM");
source.Add("NN OO AA RR EE BB FF KK");
string ToCompare = "BB GG AA FF CC MM RR II";
string word1, word2, word3, existingKey;
string[] compareList = ToCompare.Split(new string[] { " " }, StringSplitOptions.None);
Dictionary<string, int> ResultDictionary = new Dictionary<string, int>();
for (int i = 0; i < compareList.Length - 2; i++)
{
word1 = compareList[i];
for (int j = i + 1; j < compareList.Length - 1; j++)
{
word2 = compareList[j];
for (int z = j + 1; z < compareList.Length; z++)
{
word3 = compareList[z];
source.ForEach(x =>
{
if (x.Contains(word1) && x.Contains(word2) && x.Contains(word3))
{
existingKey = ResultDictionary.Keys.FirstOrDefault(y => y.Contains(word1) && y.Contains(word2) && y.Contains(word3));
if (string.IsNullOrEmpty(existingKey))
{
ResultDictionary.Add(word1 + " " + word2 + " " + word3, 1);
}
else
{
ResultDictionary[existingKey]++;
}
}
});
}
}
}
ResultDictionary will have the 3 word combinations that occur in myList1<string> with their count of occurrences. To get the total count, retrieve and add all the value fields from ResultDictionary.
EDIT:
Below snippet produces correct result with the given input,
List<string> source = new List<string>();
source.Add("2 4 6 8 10 12 14 99");
source.Add("16 18 20 22 24 26 28 102");
source.Add("33 6 97 38 50 34 87 88");
string ToCompare = "2 4 6 15 20 22 28 44";
string word1, word2, word3, existingKey;
string[] compareList = ToCompare.Split(new string[] { " " }, StringSplitOptions.None);
string[] sourceList, keywordList;
Dictionary<string, int> ResultDictionary = new Dictionary<string, int>();
source.ForEach(x =>
{
sourceList = x.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < compareList.Length - 2; i++)
{
word1 = compareList[i];
for (int j = i + 1; j < compareList.Length - 1; j++)
{
word2 = compareList[j];
for (int z = j + 1; z < compareList.Length; z++)
{
word3 = compareList[z];
if (sourceList.Contains(word1) && sourceList.Contains(word2) && sourceList.Contains(word3))
{
existingKey = ResultDictionary.Keys.FirstOrDefault(y =>
{
keywordList = y.Split(new string[] { " " }, StringSplitOptions.None);
return keywordList.Contains(word1) && keywordList.Contains(word2) && keywordList.Contains(word3);
});
if (string.IsNullOrEmpty(existingKey))
{
ResultDictionary.Add(word1 + " " + word2 + " " + word3, 1);
}
else
{
ResultDictionary[existingKey]++;
}
}
}
}
}
});
Hope this helps...
I think this will do what you're asking for:
void Main()
{
var list =
new List<String>
{
"AA BB CC DD EE FF GG HH",
"BB DD EE AA HH II JJ MM",
"NN OO AA RR EE BB FF KK"
};
var toCompare = "BB GG AA FF CC MM RR II";
var permutations = CountPermutations(list, toCompare);
}
public Int32 CountPermutations(List<String> list, String compare)
{
var words = compare.Split(' ');
return list
.Select(l => l.Split(' '))
.Select(l => new { String = String.Join(" ", l), Count = l.Join(words, li => li, wi => wi, (li, wi) => li).Count()})
.Sum(x => x.Count - 3);
}
[edit: 2/20/2019]
You can use the following to get all the matches to each list item with the total number of unique combinations
void Main()
{
var list =
new List<String>
{
"AA BB CC DD EE FF GG HH",
"BB DD EE AA HH II JJ MM",
"NN OO AA RR EE BB FF KK",
"AA AA CC DD EE FF GG HH"
};
list.Select((l, i) => new { Index = i, Item = l }).ToList().ForEach(x => Console.WriteLine($"List Item{x.Index + 1}: {x.Item}"));
var toCompare = "BB GG AA FF CC MM RR II";
Console.WriteLine($"To Compare: {toCompare}");
Func<Int32, Int32> Factorial = x => x < 0 ? -1 : x == 0 || x == 1 ? 1 : Enumerable.Range(1, x).Aggregate((c, v) => c * v);
var words = toCompare.Split(' ');
var matches = list
// Get a list of the list items with all their parts
.Select(l => new { Parts = l.Split(' '), Original = l })
// Join each part from the to-compare item to each part of the list item
.Select(l => new { String = String.Join(" ", l), Matches = l.Parts.Join(words, li => li, wi => wi, (li, wi) => li), l.Original })
// Only consider items with at least 3 matches
.Where(l => l.Matches.Count() >= 3)
// Get the each item including how many parts matched and how many unique parts there are of each part
.Select(l => new { l.Original, Matches = String.Join(" ", l.Matches), Count = l.Matches.Count(), Groups = l.Matches.GroupBy(m => m).Select(m => m.Count()) })
// To calculate the unique combinations for each match use the following mathematical equation: match_count! / (frequency_part_1! * frequency_part_2! * ... * frequency_part_n!)
.Select(l => new { l.Original, l.Matches, Combinations = Factorial(l.Count) / l.Groups.Aggregate((c, v) => c * Factorial(v)) })
.ToList();
matches.ForEach(m => Console.WriteLine($"Original: {m.Original}, Matches: {m.Matches}, Combinations: {m.Combinations}"));
var totalUniqueCombinations = matches.Sum(x => x.Combinations);
Console.WriteLine($"Total Unique Combinations: {totalUniqueCombinations}");
}

splitting of dynamic text in a textbox c#

User will enter his details in a single textbox like the following
INPUT in a textbox
S. No. Name Age Gender Concession Status Coach Seat / Berth / WL No
Current Status Coach Seat / Berth / WL No ID Type / ID No.
1 AYAN PAL 40 Male CNF S7 49 (LB) CNF S7 49 (LB)
CS CODE
int indexof1 = strMain.IndexOf("1 ");
int indexof40 = strMain.IndexOf("40 ");
int indexofstts = strMain.IndexOf("Male ");
int effectiveindexof1 = indexof1 + "1 ".Length;
int effectiveindexof40 = indexof40 + "40 ".Length;
string pname = strMain.Substring(effectiveindexof1,indexof40-effectiveindexof1);
I use substring but it won't help here because all the information provided by user will be dynamic
You can try to split it like this
var input = "1 AYAN PAL 40 Male CNF S7 49 (LB) CNF S7 49 (LB)";
var fields = input.Split(' ');
And then just access the each element like this
string id = fields[0];
string name = fields[1];
.....
Edit: diferent count of word
var fullName = string.Empty;
int i = 0;
int number = 0;
var id = fields[i++];
while (!int.TryParse(fields[i], out number))
{
fullName += fields[i++] + " ";
}
fullName = fullName.TrimEnd();
var age = fields[i++];
var gender = fields[i++];
............

Split strings that have strange pattern

I need help to split a collection of strings that have rather strange pattern.
Example data:
List<string> input = new List<string>();
input.Add("Blue Code \n 03 ID \n 05 Example \n Sky is blue");
input.Add("Green Code\n 01 ID\n 15");
input.Add("Test TestCode \n 99 \n Testing is fun");
Expected output:
For input[0]:
string part1 = "Blue"
string part2 = "Code \n 03"
string part3 = "ID \n 05"
string part4 = "Example \n Sky is blue"
For input[1]:
string part1 = "Green"
string part2 = "Code\n 01"
string part3 = "ID\n 15"
For input[2]:
string part1 = "Test"
string part2 = "TestCode \n 99"
string part3 = "\n Testing is fun"
Edited with one more example:
"038 038\n 0004 049.0\n 0006"
Expected output:
"038"
"038\n 0004"
"049.0\n 0006"
In short, I don't even know how to describe the pattern... It seems like I need the first string(act as a key) right before the "\n" as part of the new string, but the last input[2] has slightly different pattern from the other 2. Also, please take note of the spaces, they are extremely inconsistent.
I know this is a long shot, but please let me know if anyone can figure out how to deal with these data.
Updated: I think I can forget about solving this... When I actually take a look at the database in detail, I just found out that there are NOT only \n, it can be... anything, including |a |b |c (from a-z, A-Z), \a \b \c (from a-z, A-Z). Manually re-entering the data could be much more easier...
I would say the pattern is:
List<string> input = new List<string>();
input.Add("Blue Code \n 03 ID \n 05 Example \n Sky is blue");
input.Add("Green Code\n 01 ID\n 15");
input.Add("Test TestCode \n 99 \n Testing is fun");
foreach(string text in input)
{
string rest = text;
//1 Take first word
string part1 = rest.Split(' ')[0];
rest = rest.Skip(part1.Length).ToString();
//while rest contains (/n number)
while (rest.Contains("\n"))
{
//Take until /n number
int index = rest.IndexOf("\n");
string partNa = rest.Take(index).ToString();
string temp = rest.Skip(index).ToString();
string partNb = temp.Split(' ')[0];
int n;
if (int.TryParse("123", out n))
{
string partN = partNa + partNb;
rest = rest.Skip(partN.Length).ToString();
}
}
//Take rest
string part3 = rest;
}
It could probably be written a bit more optimised, but you get the idea.
Ok, I have got this little code snippet to generate the output you are looking for. the Pattern seems to be: Word [Key \n Value] [Key \n Value] [Key \n Value (With Spaces)]
Where the Key can be empty. Is that right?
var input = new List<string>
{
"Blue Code \n 03 ID \n 05 Example \n Sky is blue",
"Green Code\n 01 ID\n 15",
"038 038\n 0004 049.0\n 0006",
"Test TestCode \n 99 \n Testing is fun"
};
var output = new List<List<string>>();
foreach (var item in input)
{
var items = new List<string> {item.Split(' ')[0]};
const string strRegex = #"(?<group>[a-zA-Z0-9\.]*\s*\n\s*[a-zA-Z0-9\.]*)";
var myRegex = new Regex(strRegex, RegexOptions.None);
var matchCollection = myRegex.Matches(item.Remove(0, item.Split(' ')[0].Length));
for (var i = 0; i < 2; i++)
{
if (matchCollection[i].Success)
{
items.Add(matchCollection[i].Value);
}
}
var index = item.IndexOf(items.Last()) + items.Last().Length;
var final = item.Substring(index);
if (final.Contains("\n"))
{
items.Add(final);
}
else
{
items[items.Count -1 ] = items[items.Count - 1] + final;
}
output.Add(items);
}

Dividing a list of strings

Didn't quite know what to title this question so please feel free to edit.
I have a list of strings where all elements are strings with a length of 40.
What I want to do is split the list elements at character 20 and push the last part of the now divided string to the next element in the list, appending all other elements in the list.
E.g.
list[0] = 0011
list[1] = 2233
list[2] = 4455
^split here
// new list results in:
list[0] = 00
list[1] = 11
list[3] = 22
list[4] = 33
list[5] = 44
list[6] = 55
How can this be achieved?
list = list.SelectMany(s => new [] { s.Substring(0, 20), s.Substring(20, 20) })
.ToList();
list = list.SelectMany(x=>new[]{x.Substring(0, 20), x.Substring(20)}).ToList();
Not sure why you want to do that, but it's quite simple with linq:
List<string> split = list.SelectMany(s => new []{s.Substring(0, 2), s.Substring(2)}).ToList();
If you must work with the existing array:
const int elementCount = 3;
const int indexToSplit = 2;
string[] list = new string[elementCount * 2] { "0011", "0022", "0033", null, null, null };
for (int i = elementCount; i > 0; --i)
{
var str = list[i-1];
var left = str.Substring( 0, indexToSplit );
var right = str.Substring( indexToSplit, str.Length - indexToSplit );
var rightIndex = i * 2 - 1;
list[rightIndex] = right;
list[rightIndex - 1] = left;
}
foreach( var str in list )
{
Console.WriteLine( str );
}

How to pull out alpha and count digits using regex?

I want to build Regex in C#. I need to know how to pull out alpha and count digits using Regex.
string example = "ASDFG 3457";
Need to pull out of "ASDFG" and then count digits (eg 4 or 5 - 7). If finding 4 digits, return value = 3457 without alpha. How to do this in C#?
I know it is better to do without regex but i have a requirement that i must use regex for a reason.
If all your doing is trying to get the numbers from a piece of text you can do this:
string expr=#"\d+";
string text="ASDFG 3457":
MatchCollection mc = Regex.Matches(text, expr);
foreach (Match m in mc)
{
Console.WriteLine(m);
}
regex
(?<alpha>\w*) (?<number>\d*)
this extracts two named groups: alpha and number.
It assumes the first group only contain words and the second only contains digits and that they are separated by a blank space.
None of them are mandatory.
If you need to make them mandatory you could replace * with +
You can also force the number of digits to four with \d{4}
I'd recommend you reading a regex tutorial and take some c# sample from the web. #Srb1313711 answer already helps you on that.
Obviously (cough) the simplest "solution" is here:
using System;
using System.Collections.Generic;
class Program
{
private static IEnumerable<long> ParseNumbers(IEnumerable<char> stream)
{
bool eos = false;
using (var it = stream.GetEnumerator())
do
{
Func<bool> advance = () => !(eos = !it.MoveNext());
while (advance() && !char.IsDigit(it.Current)) ;
if (eos) break;
long accum = 0;
do accum = accum * 10 + (it.Current - '0');
while (advance() && char.IsDigit(it.Current));
yield return accum;
}
while (!eos);
}
static void Main()
{
foreach (var num in ParseNumbers("ASDFG 3457 ASDFG.\n 123457"))
{
Console.WriteLine(num);
}
}
}
For fun, of course.
Edit
For more fun: the unsafe variation. Note this is also no longer deferred, so it won't work if not all input has arrived yet, and it generates an eager list of values:
using System;
using System.Collections.Generic;
class Program
{
private static unsafe List<long> ParseNumbers(char[] input)
{
var r = new List<long>();
fixed (char* begin = input)
{
char* it = begin, end = begin + input.Length;
while (true)
{
while (it != end && (*it < '0' || *it > '9'))
++it;
if (it == end) break;
long accum = 0;
while (it != end && *it >= '0' && *it <= '9')
accum = accum * 10 + (*(it++) - '0');
r.Add(accum);
}
}
return r;
}
static void Main()
{
foreach (var number in ParseNumbers("ASDFG 3457 ASDFG.\n 123457".ToCharArray()))
{
Console.WriteLine(number);
}
}
}
Description
This regular expression will:
capture the text into group 1
count the number of digits and place them into a capture group based on how many where found
Capture group 2 will have numbers which are 8 or more digits long
Capture group 3 will have numbers which are 5-7 digits long
Capture group 4 will have numbers which are exactly 4 digits long
Capture group 5 will have numbers which are 1-3 digits long
([A-Za-z]*) (?:(\d{8,})|(\d{5,7})|(\d{4})|(\d{1,3}))
Example
Live Demo: http://www.rubular.com/r/AIO9uUNNQc
Sample Text
ASDFG 1234567890
ASDFG 123456789
ASDFG 12345678
ASDFG 1234567
ASDFG 123456
ASDFG 12345
ASDFG 1234
ASDFG 123
ASDFG 12
ASDFG 1
Capture Groups
[0][0] = ASDFG 1234567890
[0][1] = ASDFG
[0][2] = 1234567890
[0][3] =
[0][4] =
[0][5] =
[1][0] = ASDFG 123456789
[1][1] = ASDFG
[1][2] = 123456789
[1][3] =
[1][4] =
[1][5] =
[2][0] = ASDFG 12345678
[2][1] = ASDFG
[2][2] = 12345678
[2][3] =
[2][4] =
[2][5] =
[3][0] = ASDFG 1234567
[3][1] = ASDFG
[3][2] =
[3][3] = 1234567
[3][4] =
[3][5] =
[4][0] = ASDFG 123456
[4][1] = ASDFG
[4][2] =
[4][3] = 123456
[4][4] =
[4][5] =
[5][0] = ASDFG 12345
[5][1] = ASDFG
[5][2] =
[5][3] = 12345
[5][4] =
[5][5] =
[6][0] = ASDFG 1234
[6][1] = ASDFG
[6][2] =
[6][3] =
[6][4] = 1234
[6][5] =
[7][0] = ASDFG 123
[7][1] = ASDFG
[7][2] =
[7][3] =
[7][4] =
[7][5] = 123
[8][0] = ASDFG 12
[8][1] = ASDFG
[8][2] =
[8][3] =
[8][4] =
[8][5] = 12
[9][0] = ASDFG 1
[9][1] = ASDFG
[9][2] =
[9][3] =
[9][4] =
[9][5] = 1

Categories

Resources