I have a string like this:
select name,lastname,email from contacts
I want to replace the commas for +"|"+
and get something like this
select name+"|"+lastname+"|"+email from contacts
thats easy with string.Replace(",",+"|"+);
but the problem is when i face a string like this:
select name,lastname,isnull(email,0) from contacts
How i cant detect to avoid the commas inside the isnull()?
with the replace i get a string like this
select name+"|"+lastname+"|"+isnull(email+"|"+0) from contacts
and thats wrong!
thanks .
Try this:
public static string ReplaceTopLevelCommas(string query)
{
var newQuery = new StringBuilder();
var level = 0;
foreach (var c in query)
{
if (c == ',')
{
if (level == 0)
{
newQuery.Append("+\"|\"+");
}
else
{
newQuery.Append(c);
}
}
else
{
if (c == '(')
{
level++;
}
else if (c == ')')
{
level--;
}
newQuery.Append(c);
}
}
return newQuery.ToString();
}
It replaces commas only if they're not inside any parentheses. So it will also work for multiple levels of nesting.
Working example: http://ideone.com/TGPRe2
Simply write your own method:
private static string replace_commas(String str_)
{
StringBuilder str = new System.Text.StringBuilder(str_);
bool replace = true;
for(int i = 0; i != str.Length; ++i)
{
if(str[i] == ',' && replace)
str[i] = '|';
if(str[i] == '(')
{
replace = false;
continue;
}
if(str[i] == ')' && !replace)
replace = true;
}
return str.ToString();
}
You fill in the blanks! :-)
Related
So I have a fitler TextBox where I want to search for different type of docs in a grid the code where I have different type of columns such as: Date,DocId,ClientId.
For a search I write on a filter Textbox something like that DocId:2002 and It just work fine but when I try to make a multiple search for example DocId:2002 ClientId:201 It doesnt search because of the return it just does an infinite loop.
private void TextBoxFilter_TextChanged(object sender, TextChangedEventArgs e)
{
foreach (Match m in Regex.Matches((sender as TextBox).Text, pattern, options))
{
if (m.Value != "")
{
Func<String, String> untilSlash = (s) => { return filters[re.Match(s).Groups[1].ToString()] = re.Match(s).Groups[2].ToString(); };
untilSlash(m.Value);
}
}
ICollectionView cv = CollectionViewSource.GetDefaultView(this.DataGridDocList.ItemsSource);
if (filters.Count == 0)
{
cv.Filter = null;
}
else
{
cv.Filter = o =>
{
for (int i = 0; i < filters.Count; i++)
{
if (filters.ElementAt(i).Key == "Date")
{
if (DateVerify.Match(filters.ElementAt(i).Value).Success)
{
return (o as Document).DateCreated < Convert.ToDateTime(DateVerify.Match(filters.ElementAt(i).Value).Groups[1].ToString()) && (o as Document).DateCreated > Convert.ToDateTime(DateVerify.Match(filters.ElementAt(i).Value).Groups[2].ToString());
}
else
{
var dateString = (o as Document).DateCreated.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture);
return dateString.Contains(DateVerify.Match(filters.ElementAt(i).Value).Groups[1].ToString());
}
}
if (filters.ElementAt(i).Key == "DocId")
{
return (o as Document).DocumentId.ToString().Contains(filters.ElementAt(i).Value);
}
if (filters.ElementAt(i).Key == "ClientId")
{
return (o as Document).ClientId.ToUpper().Contains(filters.ElementAt(i).Value.ToUpper());
}
}
return false;
};
filters.Clear();
}
}
So my question is how can I do an big search with all the filters at one time?
Manually I can add them 1 by 1 and it will be something like search1 && search2 && search3 but It will take too much time and It's probably not the best solution
There are many ways of building up the predicate. However my suggestion is to keep it simple and just create one method that returns true or false. It's good practice to only return once in a method.
The code below if for illustration purposes (as I'm unable to test it):
ICollectionView cv = CollectionViewSource.GetDefaultView(this.DataGridDocList.ItemsSource);
if (filters.Any())
{
cv.Filter = new Predicate<object>(PredicateFilter);
}
else
{
cv.Filter = null;
}
Then Predicate method to filter results:
public bool PredicateFilter(object docObj)
{
Document doc = docObj as Document;
var response = new List<bool>();
for (int i = 0; i < filters.Count; i++)
{
if (filters.ElementAt(i).Key == "Date")
{
if (DateVerify.Match(filters.ElementAt(i).Value).Success)
{
response.Add(doc.DateCreated < Convert.ToDateTime(DateVerify.Match(filters.ElementAt(i).Value).Groups[1].ToString()) && doc.DateCreated > Convert.ToDateTime(DateVerify.Match(filters.ElementAt(i).Value).Groups[2].ToString()));
}
else
{
var dateString = doc.DateCreated.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture);
response.Add(dateString.Contains(DateVerify.Match(filters.ElementAt(i).Value).Groups[1].ToString()));
}
}
else if (filters.ElementAt(i).Key == "DocId")
{
response.Add(doc.DocumentId.ToString().Contains(filters.ElementAt(i).Value));
}
else if (filters.ElementAt(i).Key == "ClientId")
{
response.Add(doc.ClientId.ToUpper().Contains(filters.ElementAt(i).Value.ToUpper()));
}
}
return response.All(m => m); // if all filters came back with true, return 1 response of true else false.
}
I am working on building an expression tree from an infix expression. Currently I am converting to postfix and then building the tree. My code works for most expressions but not all. I am doing something wrong with my implementation of parentheses. Here is my code-
readonly static char[] operators = { '+', '-', '*', '/' };
string order_of_op(string op1, string op2)
{
if (op1 == "*" || op1 == "/")//is op1 higher?
{
return op1;//it is so return it
}
else if ((op2 == "*" || op2 == "/"))//is op2 higher
{
return op2;//it is so return it
}
else
return op1;// they are both addition or subtraction so return op1.
}
Queue<string> convert_to_postfix(string infix) //following the Shunting-yard algorithm
{
Queue<string> num_queue = new Queue<string>();
Stack<string> op_stack = new Stack<string>();
Stack<string> temp_stack = new Stack<string>();
string temp = "";
foreach (char s in infix)
{
if (operators.Contains(s) == true)//if its a function push it on the stack
{
if (temp != "")//make sure we don't push an empty string
num_queue.Enqueue(temp);
if (op_stack.Count != 0)//make sure we dont crash popping from empty stack
{
if (op_stack.Peek() != "(")//if we dont have a parenthese on top proceed as normal
{
if (op_stack.Count > 1)
{
while (op_stack.Count != 0 && order_of_op(op_stack.Peek(), s.ToString()) == op_stack.Peek())
{
num_queue.Enqueue(op_stack.Pop());
}
}
}
op_stack.Push(s.ToString());
}
else
{
op_stack.Push(s.ToString());
}
temp = "";
}
else if (s == '(')
{
op_stack.Push(s.ToString());
}
else if (s == ')')
{
if (temp!= "")
num_queue.Enqueue(temp);
temp = "";
while (op_stack.Peek() != "(")
{
num_queue.Enqueue(op_stack.Pop());
}
op_stack.Pop();
if (op_stack.Count > 1)
{
if (operators.Contains(op_stack.Peek()[0]) == true)
{
num_queue.Enqueue(op_stack.Pop());
}
}
}
else
{
temp += s;
}
}
if (temp != "")
{
num_queue.Enqueue(temp);
}
foreach (string s in op_stack)
{
num_queue.Enqueue(s);
}
Console.Write("Postfix = ");
foreach (string s in num_queue)
{
Console.Write(s);
}
Console.WriteLine();
return num_queue;
}
Thank you for any help!
Well I fixed it! All I had to change was-
if (op_stack.Count > 1)
to
if (op_stack.Count >= 1)
I want to search for a string in DataTable if it starts with "null" delete this string, if this row has no values then erase this row too. Can someone show me how to do it?
ID Name Comment
2 lola hallo
5 miky hi
null0 // delete null0 and remove this row
null1 ko // delete null1 but do not remove this row
1 hub why
3 null2 //delete null2 but do not remove this row
I tried to delete "null" but it doesn't work.
My Code:
int ct1 = 0;
for (int i = 0; i < resE1.Rows.Count; i++ )
{
if(resE1.Rows[i]["SignalName"].ToString() == "null" + ct1)
{
resE1.Rows[i].SetField<String>(2, "");
}
ct1++;
}
I find a solution to replace "null*" with empty spaces, but now I want to erase this row if the cells values of this row are empty, how can i do it?
int ct1 = 0;
for (int i = 0; i < resE1.Rows.Count; i++)
{
string fix = resE1.Rows[i]["SignalName"].ToString();
if(fix.Contains("null"))
{
resE1.Rows[i].SetField<String>(2, "");
}
ct1++;
}
I tried this. Works for me.
List<DataRow> rowsToRemove = new List<DataRow>();
foreach (DataRow dr in resE1.Rows)
{
if (dr["Name"].ToString().IndexOf("null") == 0)
{
dr.SetField("Name", "");
}
bool hasValue = false;
for (int i = 0; i < dr.ItemArray.Count(); i++)
{
if (!dr[i].ToString().Equals(String.Empty))
hasValue = true;
}
if (!hasValue) rowsToRemove.Add(dr);
}
foreach(DataRow dr in rowsToRemove)
{
dr.Delete();
}
Here is your code changed so it works although I don't like how it is written. Check the answer:
int ct1 = 0;
int i = 0;
while(i < dt.Rows.Count)
{
if ( dt.Rows[i]["Name"].ToString() == "null" + ct1)
{
if ((dt.Rows[i][0] == null || dt.Rows[i][0].ToString() == string.Empty) && (dt.Rows[i][2] == null || dt.Rows[i][2].ToString() == string.Empty))
{
dt.Rows.RemoveAt(i);
i--;
}
else
{
dt.Rows[i].SetField<String>(1, "");
}
ct1++;
}
i++;
}
Assuming your DataTable has column "Name" of type string you can achieve it like this:
private DataTable RemoveUnwanted(DataTable source)
{
var rowsEnu = source.Rows.GetEnumerator();
while (rowsEnu.MoveNext())
{
((DataRow)rowsEnu.Current)["Name"] = ((DataRow)rowsEnu.Current)["Name"].ToString().StartsWith("null") ? string.Empty : ((DataRow)rowsEnu.Current)["Name"];
}
return (from i in source.AsEnumerable()
where !(i.ItemArray.All(o => string.IsNullOrEmpty(o.ToString())))
select i).CopyToDataTable();
}
You will also need reference to System.Data.DataSetExtensions.
To answer one of your questions, to delete the entire row do something like this:
if(resE1.Rows[i].Contains("null") && (resE1.Rows[i]["ID"].ToString() == "") && (resE1.Rows[i]["Comment"].ToString() == ""))
{
resE1.Rows[i].Delete();
}
bool emptyFlag = false;
if(resE1.Rows[i].Contains("null"))
{
for(int j = 0; j < resE1.Columns.Count; j++)
{
if(resE1.Rows[i][j].Equals(""))
emptyFlag = true;
else
emptyFlag = false;
}
if(emptyFlag)
resE1.Rows[i].Delete();
}
You need something like this:
String test = "Null01";
if (test.IndexOf("Null") == 0)
{
test = test.Replace("Null", String.Empty);
}
For second part of your question, just check if Comments are null or empty then replace the string too.
Arrange code according to your own requirement.
I'm having troubles finding a string into a listbox, my string NombreCompleto is made of 3 strings that I previously had read from a file(ESSD), after I had recovered this string, I want to know if this string is in my listbox3, I tried several methods but it doesnt seem to work.
Here is my code.
foreach (string h in Directory.EnumerateFiles(NomDirec, "resume*"))
{
this.listBox1.Items.Add(h);
var NombreLinea = File.ReadLines(h);
foreach (string item in NombreLinea)
{
NombreAbuscar.Add(item.Remove(item.IndexOf(':')));
this.listBox3.Items.Add(item.Remove(item.IndexOf(':')));
}
foreach (string t in Directory.EnumerateFiles(NomDirec, "ESSD1*"))
{
string[] Nombre = File.ReadLines(t).ElementAtOrDefault(6).Split(':');
string[] ApellidoPat = File.ReadLines(t).ElementAtOrDefault(7).Split(':');
string[] ApellidoMat = File.ReadLines(t).ElementAtOrDefault(8).Split(':');
string NombreCompleto = ApellidoPat[1]+" "+ ApellidoMat[1] +","+" "+ Nombre[1];
string Nom2 = NombreCompleto.ToString();
int index = listBox3.FindString(Nom2);
if (index != -1)
{
this.listBox1.Items.Add(t);
MessageBox.Show("Find It");
}
else { MessageBox.Show("Not Found :#"); }
}
You can try with this code - based on Linq operator Where, ...
var selectedItems = from li in listBox3.Items
where li.Text == Nom2
select li.Text;
if(selectedItems.Any())
....
Try this out:
int index = -1;
for (int i = 0; i < listBox3.Items.Count; ++i)
if (listBox3.Items[i].Text == Nom2) { index = i; break; }
if (index != -1)
{
this.listBox1.Items.Add(t);
MessageBox.Show("Find It");
}
else { MessageBox.Show("Not Found :#");
Really easy way to find if a certain string is in a listbox.
private void btnAddRecipe_Click(object sender, EventArgs e)
{
bool DoesItemExist = false;
string searchString = txtRecipeName.Text;
int index = lstRecipes.FindStringExact(searchString, -1);
if (index != -1) DoesItemExist = true;
else DoesItemExist = false;
if (DoesItemExist)
{
//do something
}
else
{
MessageBox.Show("Not found", "Message", MessageBoxButtons.RetryCancel, MessageBoxIcon.Stop);
}
PopulateRecipe();
}
HI how can I validate a string, but without using regular expressions. For example how can validate this: xxx/xxxx where x is a digit? thanks
Something like that:
bool ValidateExpression(string expression)
{
string[] parts = expression.Split("/");
if (
parts.Length != 2
|| parts[0].Length != 3
|| parts[1].Length != 4
) return false;
int parsed;
return Int32.TryParse(parts[0], out parsed) && Int32.TryParse(parts[1], out parsed);
}
To be used later as
bool isValid = ValidateExpression("123/4567");
You can use Char.IsDigit to check if characters are a digit. For your specific case, you could do something like this:
public bool IsMyStringValid(string myString)
{
foreach(var c in myString)
if(!Char.IsDigit() && !c == '/') return false;
return true;
}
This is actually more specific to your case (3 digits, one '/' at index 3, followed by 4 digits):
public bool IsMyStringValid(string myString)
{
if(myString.Length != 8) return false;
for(var i = 0; i <8, i++)
if(!Char.IsDigit(myString[i]) || (i == 3 && myString[i] == '/') return false;
return true;
}
For that specific format you can use:
bool valid =
value.Length == 8 &&
value.Take(3).All(Char.IsDigit) &&
value[3] == '/' &&
value.Skip(4).All(Char.IsDigit);
Try this :
public bool ValidateString(string str)
{
var strArr = str.Split('/');
return strArr[0].All(char.IsDigit) && strArr[1].All(char.IsDigit);
}
hope this help;
I would use the .All to check something like this so no matter what the string is
if there is a non digit in it, it will not pass
public static bool IsMyStringValid(string strValidateString)
{
bool boolIsValid = false;
if (strValidateString.All(Char.IsDigit))
{
boolIsValid = true;
}
return boolIsValid;
}