IF Statement: Determine what was chosen. C# [closed] - c#

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I need to determine which condition was TRUE in an if statement if using ||.
Example:
if(trueone() || truetwo() || truethree()) {
if([magical code] == trueOne()) {
// ...do my code here...
}
}
If trueone() was true, then say that "trueOne was selected"
Or, if trueone() and truetwo() were true, then say that "trueOne and trueTwo were selected"
EDIT: No switches please.
EDIT 2:
Heres a bit more detail:
The program is meant to look through a file and its lines using a foreach statement. If the line contains a certain keyword, then print it out to the user.
Currently, the program looks like this:
foreach(string x in lines) {
if(x.Contains("stringtofind")) {
Console.WriteLine("Found stringtofind at line x");
if(x.Contains("stringtofind2")) {
Console.WriteLine("Found stringtofind2 at line x");
}
Anything more efficient that can accomplish the same task would be useful.

If this is the original code:
foreach(string x in lines) {
if(x.Contains("stringtofind")) {
Console.WriteLine("Found stringtofind at line x");
if(x.Contains("stringtofind2")) {
Console.WriteLine("Found stringtofind2 at line x");
...
}
we can see that there are a pattern that is inside the foreach loop.
In order to remove the duplicated code we can put all the stringsToFind inside an array.
Like;
var lines = new string[]
{
"line1 stringToFind1 stringToFind2",
"line2 ",
"line3 stringToFind3",
"line4 stringToFind4 stringToFind5",
};
var stringsToFind = new string[]
{
"stringToFind1",
"stringToFind2",
"stringToFind3",
"stringToFind4",
"stringToFind5",
};
foreach (string line in lines)
{
foreach (string stringToFind in stringsToFind)
{
if (line.Contains(stringToFind))
{
Console.WriteLine(string.Format("Found {0} at line {1}", stringToFind, line));
}
}
}
Now, if you want to print the number of the line instead of the line, you can a.- use a counter, b.- use a for instead of the first foreach.
for (int i = 0; i < lines.Length; i++)
{
foreach (string stringToFind in stringsToFind)
{
if (lines[i].Contains(stringToFind))
{
// We use i+1 for line number to show that in a 'human' format.
Console.WriteLine(string.Format("Found {0} at line {1}", stringToFind, (i+1)));
}
}
}

I was saying:
if the list of things to check is long... make it an actual list (for example a List<Func<bool>>)
var allConditions = new List<Func<bool>> { trueone, truetwo, truethree };
var trueConditions = allConditions.Where(p => p != null && p()).ToArray();
if (trueConditions.Length > 0)
{
if (trueConditions.Contains(trueone))
{
// ...do my code here...
}
}
and loop on it:
var allConditions = new List<Func<bool>> { trueone, truetwo, truethree };
var trueConditions = allConditions.Where(p => p != null && p()).ToArray();
if (trueConditions.Length > 0)
{
foreach (var condition in allConditions)
{
if (trueConditions.Contains(condition))
{
// ...do my code here...
}
}
}
Now, that was before you said you wanted to check...
If the line contains a certain keyword
You can do that on the framework above:
var x = "some string here to search in";
var allConditions = new List<Func<bool>> { () => x.Contains("keywords"), () => x.Contains("to"), () => x.Contains("find") };
var trueConditions = allConditions.Where(p => p != null && p()).ToArray();
if (trueConditions.Length > 0)
{
foreach (var condition in allConditions)
{
if (trueConditions.Contains(condition))
{
// ...do my code here...
}
}
}
Yet, since you only need to check for strings, you can make a list of those instead:
var x = "some string here to search in";
var allKeywords = new List<string> { "keywords", "to", "find" };
var foundKeywords = allKeywords.Where(s => x.Contains(s)).ToArray();
if (foundKeywords.Length > 0)
{
foreach (var keyword in allKeywords)
{
if (foundKeywords.Contains(keyword))
{
// ...do my code here...
}
}
}

Related

Check if List<string> exists

This is my code
List<string> list = new List<string>() { "bfd", "jy", "aaaaa", "ndnk", "ntfn", "gfm", "gfm", "mhgd5h", "srsr", "ntr", "mtmyt", "dmy", "mmy6", "ngn9d", "y6m1", "d8dm", "bbbbb", "tym", "dmj", "trsh", "tsr"};
List<string> test = new List<string>() {"aaaaa","bbbbb","ccccc","ddddd","eeeee","fffff","ggggg" };
foreach (var a in list)
{
foreach (var i in test)
{
if (i.StartsWith(a) == false)
{
Console.WriteLine(i);
}
}
}
I want to output from the list and match in the test. If the test exists, then it will not be displayed. If there is no side output,But there may be a problem with my code, it will output the same value many times
The list contains aaaaa, according to logic, aaaaa should not be output
Try this:
List<string> list = new List<string>(){"bfd", "jy", "aaaaa", "ndnk", "ntfn", "gfm", "gfm", "mhgd5h", "srsr", "ntr", "mtmyt", "dmy", "mmy6", "ngn9d", "y6m1", "d8dm", "bbbbb", "tym", "dmj", "trsh", "tsr"};
List<string> test = new List<string>(){"aaaaa", "bbbbb", "ccccc", "ddddd", "eeeee", "fffff", "ggggg"};
foreach (var a in list)
{
if (!test.Contains(a))
{
Console.WriteLine(a);
}
}
There are simple solutions using LINQ. But since I assume this is an exercise, I will show you the detailed version using loops.
The problem is that the WriteLine is inside the inner loop. Therefore you will get many repetitions. Store the outcome of the test in a Boolean variable and place the display part after the inner loop.
foreach (var a in list)
{
bool found = false;
foreach (var i in test)
{
if (i.StartsWith(a))
{
found = true;
break; // Exit the inner loop
}
}
if (!found)
{
Console.WriteLine(a); // We must output a here since i out of scope.
}
}
Also, if you want to know whether a specific string is contained in the list, you should probably replace i.StartsWith(a) with i == a.
The code becomes easier to read, if you extract the list search into its own method
private bool IsInList(List<string> list, string item)
{
foreach (string s in list)
{
if (s == item)
{
return true;
}
}
return false;
}
Now, you don't need the Boolean variable any more
foreach (var a in list)
{
if (!IsInList(test, a))
{
Console.WriteLine(a);
}
}
I used !condition (pronounce: "not condition") instead of condition == false. It's terser.
I assume that this is an exercise. In production code you would simply use the built in method Contains of the list.
foreach (var a in list)
{
if (!test.Contains(a))
{
Console.WriteLine(a);
}
}
or even (as #mjwills suggests in his comment):
foreach (var a in list.Except(test)) {
Console.WriteLine(a);
}

How to remove texts after a character?

I have an array that holds user and passwords in user:pass form, and I like ro remove lines which pass is less than 8 characters or password uses repetitive chars like 111111,22222222222,...
I have tried string.take but it takes lines completely, I need conditional deletion.
public string[] lines;
//open file dialogue to load the user pass file
lines = File.ReadAllLines(openFileDialog1.FileName);
//delete button click event
//the place that I have problem
I have email:pass combination like so:
email1:1234567895121
email2:12345
email4:11111
email5"454545454545
and I would like the output to be like
email1:1234567895121
email5"454545454545
Just loop the characters of every line and see if the current is equal to the previous:
public string[] lines = File.ReadAllLines(openFileDialog1.FileName);
var filteredLines = new List<string>(lines);
foreach(var line in lines)
{
var pair = line.Split(':');
var mail = pair[0];
var pass = pair[1]; // may throw exception on invalid format of your line
for(int i = 1; i < pass.Length; i++)
{
if(pass[i] == pass[i - 1])
{
filteredLines.Remove(line);
break; // will break inner loop and continue on next line
}
}
}
string[] lines =
{
"email1:1234567895121",
"email2:12345",
"email3:22222222222",
"email4:11111",
"email5:454545454545"
};
lines = lines
.Where(s =>
{
string pass = s.Split(new[] { ':' }, 2)[1];
return pass.Length >= 8 && pass.Any(c => c != pass[0]);
})
.ToArray();
foreach (var s in lines)
Console.WriteLine(s);
Output:
email1:1234567895121
email5:454545454545

Parse command line string into a list of strings [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I want to take the following string as input:
first-arg second-arg "third arg with spaces" "arg with \" quotes"
and return this list of strings as output
["first-arg", "second-arg", "third arg with spaces", "arg with \" quotes"]
Are there any nuget packages or built in functions that can do this? I want it to handle edge cases like arguments containing multiple words and arguments containing quotes.
string[] arguments = Environment.GetCommandLineArgs();
For more information see the MSDN website
This class satisfies the requirements. It's not the most effective way, but it returns the right arguments.
public static class ArgumentLineParser
{
public static string[] ToArguments(string cmd)
{
if (string.IsNullOrWhiteSpace(cmd))
{
return new string[0];
}
var argList = new List<string>();
var parseStack = new Stack<char>();
bool insideLiteral = false;
for (int i = 0; i < cmd.Length; i++)
{
bool isLast = i + 1 >= cmd.Length;
if (char.IsWhiteSpace(cmd[i]) && insideLiteral)
{
// Whitespace within literal is kept
parseStack.Push(cmd[i]);
}
else if (char.IsWhiteSpace(cmd[i]))
{
// Whitespace delimits arguments
MoveArgumentToList(parseStack, argList);
}
else if (!isLast && '\\'.Equals(cmd[i]) && '"'.Equals(cmd[i + 1]))
{
//Escaped double quote
parseStack.Push(cmd[i + 1]);
i++;
}
else if ('"'.Equals(cmd[i]) && !insideLiteral)
{
// Begin literal
insideLiteral = true;
}
else if ('"'.Equals(cmd[i]) && insideLiteral)
{
// End literal
insideLiteral = false;
}
else
{
parseStack.Push(cmd[i]);
}
}
MoveArgumentToList(parseStack, argList);
return argList.ToArray();
}
private static void MoveArgumentToList(Stack<char> stack, List<string> list)
{
var arg = string.Empty;
while (stack.Count > 0)
{
arg = stack.Pop() + arg;
}
if (arg != string.Empty)
{
list.Add(arg);
}
}
}
It can be used like this:
var line = #"first-arg second-arg ""third arg with spaces"" ""arg with \"" quotes""";
var args = ArgumentLineParser.ToArguments(line);

Find two strings in list with a regular expression

I need to find two strings within a list that contains the characters from another string, which are not in order. To make it clear, an example could be a list of animals like:
lion
dog
bear
cat
And a given string is: oodilgn.
The answer here would be: lion and dog
Each character from the string will be used only once.
Is there a regular expression that will allow me to do this?
You could try to put the given string between []. These brackets will allow choosing - in any order - from these letters only. This may not be a perfect solution, but it will catch the majority of your list.
For example, you could write oodilgn as [oodilgn], then add a minimum number of letters to be found - let's say 3 - by using the curly brackets {}. The full regex will be like this:
[oodilgn]{3,}
This code basically says: find any word that has three of the letters that are located between brackets in any order.
Demo: https://regex101.com/r/MCWHjQ/2
Here is some example algorithm that does the job. I have assumed that the two strings together don't need to take all letters from the text else i make additional commented check. Also i return first two appropriate answers.
Here is how you call it in the outside function, Main or else:
static void Main(string[] args)
{
var text = "oodilgn";
var listOfWords = new List<string> { "lion", "dog", "bear", "cat" };
ExtractWordsWithSameLetters(text, listOfWords);
}
Here is the function with the algorithm. All string manuplations are entirely with regex.
public static void ExtractWordsWithSameLetters(string text, List<string> listOfWords)
{
string firstWord = null;
string secondWord = null;
for (var i = 0; i < listOfWords.Count - 1; i++)
{
var textCopy = text;
var firstWordIsMatched = true;
foreach (var letter in listOfWords[i])
{
var pattern = $"(.*?)({letter})(.*?)";
var regex = new Regex(pattern);
if (regex.IsMatch(text))
{
textCopy = regex.Replace(textCopy, "$1*$3", 1);
}
else
{
firstWordIsMatched = false;
break;
}
}
if (!firstWordIsMatched)
{
continue;
}
firstWord = listOfWords[i];
for (var j = i + 1; j < listOfWords.Count; j++)
{
var secondWordIsMatched = true;
foreach (var letter in listOfWords[j])
{
var pattern = $"(.*?)({letter})(.*?)";
var regex = new Regex(pattern);
if (regex.IsMatch(text))
{
textCopy = regex.Replace(textCopy, "$1*$3", 1);
}
else
{
secondWordIsMatched = false;
break;
}
}
if (secondWordIsMatched)
{
secondWord = listOfWords[j];
break;
}
}
if (secondWord == null)
{
firstWord = null;
}
else
{
//if (textCopy.ToCharArray().Any(l => l != '*'))
//{
// break;
//}
break;
}
}
if (firstWord != null)
{
Console.WriteLine($"{firstWord} { secondWord}");
}
}
Function is far from optimised but does what you want. If you want to return results, not print them just create an array and stuff firstWord and secondWord in it and have return type string[] or add two paramaters with ref out In those cases you will need to check the result in the calling function.
please try this out
Regex r=new Regex("^[.*oodilgn]$");
var list=new List<String>(){"lion","dog","fish","god"};
var output=list.Where(x=>r.IsMatch(x));
result
output=["lion","dog","god"];

C#: Collection was modified; enumeration operation may not execute [duplicate]

This question already has answers here:
How to remove elements from a generic list while iterating over it?
(28 answers)
Closed 9 years ago.
My goal is to delete a user from the user list in my application.But i cannot get to the bottom of this error. Some one plz bail me out.
if (txtEmailID.Text.Length > 0)
{
users = UserRespository.GetUserName(txtEmailID.Text);
bool isUserAvailable=false;
foreach (EduvisionUser aUser in users) // Exception thrown in this line
{
isUserAvailable = true;
if(!aUser.Activated)
{
users.Remove(aUser);
}
}
if (users.Count == 0 && isUserAvailable)
{
DeactivatedUserMessage();
return;
}
}
You can't modify a collection while you're iterating over it with a foreach loop. Typical options:
Use a for loop instead
Create a separate collection of the items you want to act on, then iterate over that.
Example of the second approach:
List<EduvisionUser> usersToRemove = new List<EduvisionUser>();
foreach (EduvisionUser aUser in users) --->***Exception thrown in this line***
{
isUserAvailable = true;
if(!aUser.Activated)
{
usersToRemove.Add(aUser);
}
}
foreach (EduvisionUser userToRemove in usersToRemove)
{
users.Remove(userToRemove);
}
Another alternative, if you're using List<T> is to use List<T>.RemoveAll:
isUserAvailable = users.Count > 0;
users.RemoveAll(user => !user.Activated);
You are trying to delete a user from the list you are looping trough.
this is impossible. Best is to create a new list and add the good ones in it instead of deleting the bad ones
if (txtEmailID.Text.Length > 0)
{
//#new list
List<EduvisionUser> listOfAcceptedUsers = new List<EduvisionUser>()**
users = UserRespository.GetUserName(txtEmailID.Text);
bool isUserAvailable=false;
foreach (EduvisionUser aUser in users) --->***Exception thrown in this line***
{
isUserAvailable = true;
//Add user to list instead of deleting
if(aUser.Activated)
{
ListOfAcceptedUsers.Add(aUser);
}
}
//check new list instead of old one
if (ListOfAcceptedUsers.Count == 0 && isUserAvailable)
{
DeactivatedUserMessage();
return;
}
}
you can do it like this. Use for instead foreach
for( int i =0; i< users.Count; i++ ) --->***Exception thrown in this line***
{
EduvisionUser aUser = users[i];
isUserAvailable = true;
if(!aUser.Activated)
{
users.Remove(aUser);
i--;
}
}
You cannot modify the collection while enumerating. Instead of removing select only what you need and leave the Garbage Collector take care of the rest:
users = users.Where(x => x.Activated);
Or even better, select only what you need from the repository:
users = UserRespository.GetUserName(txtEmailID.Text).Where(x => x.Activated);
My goal is to delete a WorkCalendar from the WorkCalendar but when select Wc that has WorkHour thrown an exception like this:" Collection was modified; enumeration operation may not execute." Any ideas? thanks for the help
Delete method:
try
{
if (!this.DataWorkspace.ApplicationData.WorkCalendars.CanDelete)
{
this.ShowMessageBox("", "", MessageBoxOption.Ok);
return;
}
if (this.WorkCalendars.SelectedItem != null)
{
if ((this.WorkCalendars.SelectedItem.FindCalendarWPs.Count() > 0) || (this.WorkCalendars.SelectedItem.FindCalendarWPs1.Count() > 0))
{
Microsoft.LightSwitch.Threading.Dispatchers.Main.BeginInvoke
(() =>
{
RadWindow.Alert(" ");
});
return;
}
var y = DataWorkspace.ApplicationData.WorkCalendarDays.Where(w => w.WorkCalendar.Id == WorkCalendars.SelectedItem.Id).Execute().AsEnumerable();
foreach (var item in y)
{
if(item.WorkingHoursCollection != null && item.WorkingHoursCollection.Count() > 0)
foreach (var WH in item.WorkingHoursCollection)
{
WH.Delete();
}
item.Delete();
}
if (this.WorkCalendars.SelectedItem == this.DataWorkspace.ApplicationData.WorkCalendars.Where(U => U.Id == this.WorkCalendars.SelectedItem.Id).SingleOrDefault())
{
Microsoft.LightSwitch.Threading.Dispatchers.Main.BeginInvoke
(() =>
{
RadWindow.Alert(" ");
});
return;
}
this.WorkCalendars.SelectedItem.Delete();
this.Save();
}
}
catch (Exception ex)
{
Microsoft.LightSwitch.Threading.Dispatchers.Main.BeginInvoke
(() =>
{
var msg = new LightSwitchApplication.Presentation.GeneralViews.ExceptionMessage();
msg.DataContext = ex;
msg.ShowDialog();
});
}

Categories