Array not working when more than one value is provided - c#

This is my code for my Page_Load:
string _group_array = Group_Array.Get_Group_Array(3);
string[] groups = new string[] { _group_array };
foreach (string group in groups)
{
GridView grdv = new GridView();
grdv.DataSource = Connections.isp_GET_GRIDVIEW_DATA("STDNG", group, "", "");
grdv.DataBind();
gridview_holder.Controls.Add(grdv);
}
And this is the code for my Group_Array class:
public static String Get_Group_Array(int count)
{
string _cs_group_array = "";
if(count == 1)
{
_cs_group_array = "A";
}
else if(count == 2)
{
_cs_group_array = "A, B";
}
else if (count == 3)
{
_cs_group_array = "A, B, C";
}
return _cs_group_array;
}
My issue is that when my count is greater than 1, my groups does not work. Any ideas as to why?

Problem1 : you are not seperating the group string _group_array using comma as delimiter .
Solution1 : you need to split the group string _group_array using comma as delimiter.
Note: you can use Split() function for Splitting the string.
Replace This:
string[] groups = new string[] { _group_array };
With This:
string[] groups = _group_array.Split(',');
Problem 2: you have spaces between the strings.
Solution 2: you need to remove the spaces between the strings.
Replace This:
else if(count == 2)
{
_cs_group_array = "A, B";
}
else if (count == 3)
{
_cs_group_array = "A, B, C";
}
With This:
else if(count == 2)
{
_cs_group_array = "A,B";
}
else if (count == 3)
{
_cs_group_array = "A,B,C";
}
Complete Code:
string _group_array = Group_Array.Get_Group_Array(3);
string[] groups = _group_array.Split(',');
foreach (string group in groups)
{
GridView grdv = new GridView();
grdv.DataSource = Connections.isp_GET_GRIDVIEW_DATA("STDNG", group, "", "");
grdv.DataBind();
gridview_holder.Controls.Add(grdv);
}
public static String Get_Group_Array(int count)
{
string _cs_group_array = "";
if(count == 1)
{
_cs_group_array = "A";
}
else if(count == 2)
{
_cs_group_array = "A,B";
}
else if (count == 3)
{
_cs_group_array = "A,B,C";
}
return _cs_group_array;
}

I'm going to suggest what I think is a cleaner approach:
string[] groups = new [] { "A", "B", "C" }.Take(count);

Your Get_Group_Array method always returns one string, not a string array.That's why your foreach is executing only once because your groups array has only one element. According to your code you can change your method like this:
public static string[] Get_Group_Array(int count)
{
string _cs_group_array = "";
if(count == 1)
{
_cs_group_array = "A";
}
else if(count == 2)
{
_cs_group_array = "A, B";
}
else if (count == 3)
{
_cs_group_array = "A, B, C";
}
return _cs_group_array.Split(',');
}
Then call it:
string[] groups = Group_Array.Get_Group_Array(3);
If you want to make it better:
public static string[] Get_Group_Array(int count)
{
string[] chars = new string[count];
for (int i = 0; i < count; i++)
{
chars[i] = ((char) i + 65).ToString();
}
return chars;
}

Related

How to parse nested parenthesis only in first level in C#

I would like to write C# code that parses nested parenthesis to array elements, but only on first level. An example is needed for sure:
I want this string:
"(example (to (parsing nested paren) but) (first lvl only))"
tp be parsed into:
["example", "(to (parsing nested paren) but)", "(first lvl only)"]
I was thinking about using regex but can't figure out how to properly use them without implementing this behaviour from scratch.
In the case of malformed inputs I would like to return an empty array, or an array ["error"]
I developed a parser for your example. I also checked some other examples which you can see in the code.
using System;
using System.Collections;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
string str = "(example (to (parsing nested paren) but) (first lvl only))"; // => [example , (to (parsing nested paren) but) , (first lvl only)]
//string str = "(first)(second)(third)"; // => [first , second , third]
//string str = "(first(second)third)"; // => [first , (second) , third]
//string str = "(first(second)(third)fourth)"; // => [first , (second) , (third) , fourth]
//string str = "(first((second)(third))fourth)"; // => [first , ((second)(third)) , fourth]
//string str = "just Text"; // => [ERROR]
//string str = "start with Text (first , second)"; // => [ERROR]
//string str = "(first , second) end with text"; // => [ERROR]
//string str = ""; // => [ERROR]
//string str = "("; // => [ERROR]
//string str = "(first()(second)(third))fourth)"; // => [ERROR]
//string str = "(((extra close pareanthese))))"; // => [ERROR]
var res = Parser.parse(str);
showRes(res);
}
static void showRes(ArrayList res)
{
var strings = res.ToArray();
var theString = string.Join(" , ", strings);
Console.WriteLine("[" + theString + "]");
}
}
public class Parser
{
static Dictionary<TokenType, TokenType> getRules()
{
var rules = new Dictionary<TokenType, TokenType>();
rules.Add(TokenType.OPEN_PARENTHESE, TokenType.START | TokenType.OPEN_PARENTHESE | TokenType.CLOSE_PARENTHESE | TokenType.SIMPLE_TEXT);
rules.Add(TokenType.CLOSE_PARENTHESE, TokenType.SIMPLE_TEXT | TokenType.CLOSE_PARENTHESE);
rules.Add(TokenType.SIMPLE_TEXT, TokenType.SIMPLE_TEXT | TokenType.CLOSE_PARENTHESE | TokenType.OPEN_PARENTHESE);
rules.Add(TokenType.END, TokenType.CLOSE_PARENTHESE);
return rules;
}
static bool isValid(Token prev, Token cur)
{
var rules = Parser.getRules();
return rules.ContainsKey(cur.type) && ((prev.type & rules[cur.type]) == prev.type);
}
public static ArrayList parse(string sourceText)
{
ArrayList result = new ArrayList();
int openParenthesesCount = 0;
Lexer lexer = new Lexer(sourceText);
Token prevToken = lexer.getStartToken();
Token currentToken = lexer.readNextToken();
string tmpText = "";
while (currentToken.type != TokenType.END)
{
if (currentToken.type == TokenType.OPEN_PARENTHESE)
{
openParenthesesCount++;
if (openParenthesesCount > 1)
{
tmpText += currentToken.token;
}
}
else if (currentToken.type == TokenType.CLOSE_PARENTHESE)
{
openParenthesesCount--;
if (openParenthesesCount < 0)
{
return Parser.Error();
}
if (openParenthesesCount > 0)
{
tmpText += currentToken.token;
}
}
else if (currentToken.type == TokenType.SIMPLE_TEXT)
{
tmpText += currentToken.token;
}
if (!Parser.isValid(prevToken, currentToken))
{
return Parser.Error();
}
if (openParenthesesCount == 1 && tmpText.Trim() != "")
{
result.Add(tmpText);
tmpText = "";
}
prevToken = currentToken;
currentToken = lexer.readNextToken();
}
if (openParenthesesCount != 0)
{
return Parser.Error();
}
if (!Parser.isValid(prevToken, currentToken))
{
return Parser.Error();
}
if (tmpText.Trim() != "")
{
result.Add(tmpText);
}
return result;
}
static ArrayList Error()
{
var er = new ArrayList();
er.Add("ERROR");
return er;
}
}
class Lexer
{
string _txt;
int _index;
public Lexer(string text)
{
this._index = 0;
this._txt = text;
}
public Token getStartToken()
{
return new Token(-1, TokenType.START, "");
}
public Token readNextToken()
{
if (this._index >= this._txt.Length)
{
return new Token(-1, TokenType.END, "");
}
Token t = null;
string txt = "";
if (this._txt[this._index] == '(')
{
txt = "(";
t = new Token(this._index, TokenType.OPEN_PARENTHESE, txt);
}
else if (this._txt[this._index] == ')')
{
txt = ")";
t = new Token(this._index, TokenType.CLOSE_PARENTHESE, txt);
}
else
{
txt = this._readText();
t = new Token(this._index, TokenType.SIMPLE_TEXT, txt);
}
this._index += txt.Length;
return t;
}
private string _readText()
{
string txt = "";
int i = this._index;
while (i < this._txt.Length && this._txt[i] != '(' && this._txt[i] != ')')
{
txt = txt + this._txt[i];
i++;
}
return txt;
}
}
class Token
{
public int position
{
get;
private set;
}
public TokenType type
{
get;
private set;
}
public string token
{
get;
private set;
}
public Token(int position, TokenType type, string token)
{
this.position = position;
this.type = type;
this.token = token;
}
}
[Flags]
enum TokenType
{
START = 1,
OPEN_PARENTHESE = 2,
SIMPLE_TEXT = 4,
CLOSE_PARENTHESE = 8,
END = 16
}
well, regex will do the job:
var text = #"(example (to (parsing nested paren) but) (first lvl only))";
var pattern = #"\(([\w\s]+) (\([\w\s]+ \([\w\s]+\) [\w\s]+\)) (\([\w\s]+\))\)*";
try
{
Regex r = new Regex(pattern, RegexOptions.IgnoreCase);
Match m = r.Match(text);
string group_1 = m.Groups[1].Value; //example
string group_2 = m.Groups[2].Value; //(to (parsing nested paren) but)
string group_3 = m.Groups[3].Value; //(first lvl only)
return new string[]{group_1,group_2,group_3};
}
catch(Exception ex){
return new string[]{"error"};
}
hopefully this helps, tested here in dotnetfiddle
Edit:
this might get you started into building the right expression according to whatever patterns you are falling into and maybe build a recursive function to parse the rest into the desired output :)
RegEx is not recursive. You either count bracket level, or recurse.
An non-recursive parser loop I tested for the example you show is..
string SplitFirstLevel(string s)
{
List<string> result = new List<string>();
int p = 0, level = 0;
for (int i = 0; i < s.Length; i++)
{
if (s[i] == '(')
{
level++;
if (level == 1) p = i + 1;
if (level == 2)
{
result.Add('"' + s.Substring(p, i - p) + '"');
p = i;
}
}
if (s[i] == ')')
if (--level == 0)
result.Add('"' + s.Substring(p, i - p) + '"');
}
return "[" + String.Join(",", result) + "]";
}
Note: after some more testing, I see your specification is unclear. How to delimit orphaned level 1 terms, that is terms without bracketing ?
For example, my parser translates
(example (to (parsing nested paren) but) (first lvl only))
to:
["example ","(to (parsing nested paren) but) ","(first lvl only)"]
and
(example (to (parsing nested paren)) but (first lvl only))
to:
["example ","(to (parsing nested paren)) but ","(first lvl only)"]
In either case, "example" gets a separate term, while "but" is grouped with the first term. In the first example this is logical, it is in the bracketing, but it may be unwanted behaviour in the second case, where "but" should be separated, like "example", which also has no bracketing (?)

Find next string in a list of string

I have a list of UserNames in a comma delimited string. I want to find next one of the input username.
For Example:
var s0 = "abc,deF,ghi,jkl";
var s1 = "abc";
var s2 = "def";
var s3 = "ghi";
var s4 = "jkl";
Result should be:
NextInString(s0,s1 ) == "def"
NextInString(s0,s2 ) == "ghi"
NextInString(s0,s3 ) == "jkl"
NextInString(s0,s4 ) == "jkl"
Here is what I have:
string NextInString(string listOfNames, string userName)
{
if(listOfNames == string.Empty || userName == string.Empty)
return string.Empty;
var s = listOfNames.Split(',');
var count = 0;
foreach (var element in s)
{
if (element == userName)break;
count++;
}
if (s.Length -1 == count)
{
return s[count];
}
else return s[ count + 1 ];
}
My question is, is there a better/easier way to approach this?
If you take the extra step to ensure your string list is trimmed, you can just use the IndexOf() method of List<T>:
string csv = "test1, test2, test3, test4";
List<string> names = csv.Split(',').Select(x => x.Trim()).ToList();
Then your NextInString() method (I think this is a poorly named method) would look like this:
private static string NextInString(List<string> names, string userName)
{
int index = names.IndexOf(userName);
if(names.Count - 1 == index || index == -1)
{
return "No result";
}
else
{
return names[index + 1];
}
}
I made a fiddle here
You can use Linq like this:
string userName = "abc";
string listOfNames = "abc,xyz,123";
var names = listOfNames
.Split(',')
.Select((n, i) => new {name = n, index =i} )
.ToArray();
var firstMatch = names.FirstOrDefault(n => n.name == userName);
var result = firstMatch == null
? string.Empty
: firstMatch.index == names.Length - 1
? string.Empty
: names[firstMatch.index + 1].name;
Here is the LINQ approach:
string NextInString(string listOfNames, string userName)
{
if(listOfNames == string.Empty || userName == string.Empty) return string.Empty;
var names = listOfNames.Split(',');
return names
.SkipWhile(x => x != userName)
.Skip(1)
.FirstOrDefault() ?? names.Last();
}
You can make a nice little extension method to do this after the string is split, like so:
static class IListExtensions
{
public static T FindItemAfter<T>(this IList<T> list, T targetItem)
{
return list[list.IndexOf(targetItem)+ 1];
}
}
You can use it like this:
static void Main(string[] args)
{
var list = "cat,dog,rat".Split(',');
Console.WriteLine(list.FindItemAfter("cat"));
Console.WriteLine(list.FindItemAfter("dog"));
Console.ReadLine();
}
It returns:
dog
rat
This overload will allow you to specify a default value that gets returned if the requested item isn't found, or the next item would be outside the list.
public static T FindItemAfter<T>(this IList<T> list, T targetItem, T defaultValue)
{
var index = list.IndexOf(targetItem);
if (index == -1 || index >= list.Count - 1)
{
return defaultValue;
}
return list[index + 1];
}
How about something like this?
var s = listOfNames.Split(',');
for (var i = 0; i < s.count; i++)
{
if (i == s.count - 1)
{
return string.Format("No user after {0} was found", userName);
}
else if (s[i] == userName)
{
return s[i + 1];
}
}

How to split a item in array to two item with conditional?

I have an example above.
Have array like:
array[0] = TODO 06:15PMJoin Michael
array[1] = WakeUp
array[2] = Going to schools
I want it become like:
array[0] = TODO 06:15PM
array[1] = Join Michael
array[2] = WakeUp
array[3] = Going to schools
In this example, I split item have content TODO 06:15PMJoin Michael to new two item.
Have two separate questions here:
How to create a role for creating a new item in an array?
I tried with my code:
var splitList = words.SelectMany(x => x.Contains("AM") || x.Contains("PM"))
But I don't know how to split from text AM or PM to the new item in arrays.
You can try finding AM/PM and get substrings:
String[] array = new String[] {
"TODO 06:15PMJoin Michael",
"WakeUp",
"Going to schools"
};
var result = array
.SelectMany(line => {
int p = line.IndexOf("AM");
if (p >= 0)
return new String[] {
line.Substring(0, p + "AM".Length),
line.Substring(p + "AM".Length) };
p = line.IndexOf("PM");
if (p >= 0)
return new String[] {
line.Substring(0, p + "PM".Length),
line.Substring(p + "PM".Length) };
return new String[] { line };
}
);
//.ToArray(); // if you want to have array representation
// Test
Console.Write(String.Join(Environment.NewLine, result));
You can also try this:
string[] array = new string[] {"TODO 06:15PMJoin Michael",
"WakeUp",
"Going to schools"};
string[] SplitArray(string[] array)
{
List<string> returnArray = new List<string>();
foreach (string item in array)
{
int index = GetIndex(item);
if (index >= 0)
{
string s1 = item.Substring(0, index + 2);
string s2 = item.Substring(index + 2);
returnArray.Add(s1);
returnArray.Add(s2);
}
else
{
returnArray.Add(item);
}
}
return returnArray.ToArray();
}
int GetIndex(string s)
{
int index = GetIndexOf(s, "AM");
if (index == -1)
{
index = GetIndexOf(s, "PM");
}
return index;
}
int GetIndexOf(string s, string delim)
{
int index = -1;
int tempIndex = 0;
do
{
tempIndex = s.IndexOf(delim, tempIndex);
if (tempIndex > 0)
{
if (char.IsDigit(s[tempIndex-1]))
{
index = tempIndex;
break;
}
}
}
while(tempIndex >= 0);
return index;
}

Compare strings for equality

I want to compare a collection of strings and return the the equal parts until a not equal part occurs. (and remove traling whitespace).
example:
List<string> strList = new List<string>
{
"string xyz stop",
"string abc stop",
"string qrt stop"
};
string result = GetEqualName(strList); // This should return "string"
I made the following method that works
string GetEqualName(IEnumerable<string> strList)
{
string outString = "";
bool firstTime = true;
foreach (var subString in strList)
{
if (firstTime)
{
outString = subString;
firstTime = false;
}
else
{
string stringBuilder = "";
for (int i = 0; i < outString.Count(); i++)
{
if (outString[i] == subString[i])
stringBuilder = stringBuilder + outString[i];
else
break;
}
outString = stringBuilder;
}
}
outString = outString.TrimEnd(' '); // Remove traling whitespace
return outString;
}
I just feel that this is something that can be done in a few lines and I am overdoing it. Do you guys have any suggestions?
You can Zip two strings together, take the pairs that are equal, and then create a string of those characters.
public static string LargestCommonPrefix(string first, string second)
{
return new string(first.Zip(second, Tuple.Create)
.TakeWhile(pair => pair.Item1 == pair.Item2)
.Select(pair => pair.Item1)
.ToArray());
}
Once you've solved the problem for the case of combining two strings, you can easily apply it to a sequence of strings:
public static string LargestCommonPrefix(IEnumerable<string> strings)
{
return strings.Aggregate(LargestCommonPrefix);
}
This little function does basically the same as your version, but shorter.
string GetEqualName(IEnumerable<string> strList)
{
int limit = strList.Min(s => s.Length);
int i = 0;
for (; i < limit; i++)
{
if (strList.Select(s => s.Substring(0,i+1)).Distinct().Count() > 1)
{
break;
}
}
return strList.First().Substring(0, i).Trim();
}
Here's a different method which does what you want. I looks for the longest common substring from left to right using a HashSet<string>:
string GetCommonStartsWith(IEnumerable<string> strList, StringComparer comparer = null)
{
if(!strList.Any() || strList.Any(str => string.IsNullOrEmpty(str)))
return null;
if(!strList.Skip(1).Any())
return strList.First(); // only one
if(comparer == null) comparer = StringComparer.CurrentCulture;
int commonLength = strList.Min(str => str.Length);
for (int length = commonLength; length > 0; length--)
{
HashSet<string> duptester = new HashSet<string>(comparer);
string first = strList.First().Substring(0, length).TrimEnd();
duptester.Add(first);
bool allEqual = strList.Skip(1)
.All(str => !duptester.Add(str.Substring(0, length).TrimEnd()));
if (allEqual)
return first;
}
return null;
}
Here's a version that uses less LINQ than some of the other answers and might possibly be more performant.
string GetEqualName(IEnumerable<string> strList)
{
StringBuilder builder = new StringBuilder();
int minLength = strList.Min(s => s.Length);
for (int i = 0; i < minLength; i++)
{
char? c = null;
foreach (var s in strList)
{
if (c == null)
c = s[i];
else if (s[i] != c)
return builder.ToString().TrimEnd();
}
builder.Append(c);
}
return builder.ToString().TrimEnd();
}

How to Get Data from index of String

I'm new in c#. and I have some Question...
I have String following this code
string taxNumber = "1222233333445";
I want to get data from This string like that
string a = "1"
string b = "2222"
string c = "33333"
string d = "44"
string e = "5"
Please Tell me about Method for get Data From String.
Thank You Very Much ^^
Use the String.Substring(int index, int length) method
string a = taxNumber.Substring(0, 1);
string b = taxNumber.Substring(1, 4);
// etc
Oh well, the best I can come up with is this:
IEnumerable<string> numbers
= taxNumber.ToCharArray()
.Distinct()
.Select(c => new string(c, taxNumber.Count(t => t == c)));
foreach (string numberGroup in numbers)
{
Console.WriteLine(numberGroup);
}
Outputs:
1
2222
33333
44
5
This can also do , you dont need to fix the no of characters, you can check by changing the no of 1's , 2's etc
string taxNumber = "1222233333445";
string s1 = taxNumber.Substring(taxNumber.IndexOf("1"), ((taxNumber.Length - taxNumber.IndexOf("1")) - (taxNumber.Length - taxNumber.LastIndexOf("1"))) + 1);
string s2 = taxNumber.Substring(taxNumber.IndexOf("2"), ((taxNumber.Length - taxNumber.IndexOf("2")) - (taxNumber.Length - taxNumber.LastIndexOf("2"))) + 1);
string s3 = taxNumber.Substring(taxNumber.IndexOf("3"), ((taxNumber.Length - taxNumber.IndexOf("3")) - (taxNumber.Length - taxNumber.LastIndexOf("3"))) + 1);
You can use Char.IsDigit to identify digits out of string, and may apply further logic as follows:
for (int i=0; i< taxNumber.Length; i++)
{
if (Char.IsDigit(taxNumber[i]))
{
if(taxNumber[i-1]==taxNumber[i])
{
/*Further assign values*/
}
}
Try this Code
string taxNumber = "1222233333445";
char[] aa = taxNumber.ToCharArray();
List<string> finals = new List<string>();
string temp = string.Empty;
for (int i = 0; i < aa.Length; i++)
{
if (i == 0)
{
temp = aa[i].ToString();
}
else
{
if (aa[i].ToString() == aa[i - 1].ToString())
{
temp += aa[i];
}
else
{
if (temp != string.Empty)
{
finals.Add(temp);
temp = aa[i].ToString();
}
}
if (i == aa.Length - 1)
{
if (aa[i].ToString() != aa[i - 1].ToString())
{
temp = aa[i].ToString();
finals.Add(temp);
}
else
{
finals.Add(temp);
}
}
}
}
and check value of finals string list
you may use regex:
string strRegex = #"(1+|2+|3+|4+|5+|6+|7+|8+|9+|0+)";
RegexOptions myRegexOptions = RegexOptions.None;
Regex myRegex = new Regex(strRegex, myRegexOptions);
string strTargetString = #"1222233333445";
return myRegex.Split(strTargetString);

Categories