I am working on a program which needs to enter values in an array in a loop. I need a way to find the largest index:
string[] stuff = { "Headphones", "Pen", "stapler" };
string[] alreadysaid = { "Headphones" };
foreach (string stuffs in stuff)
{
if (alreadysaid.Contains(stuffs))
{
Console.WriteLine("already said");
}
else
{
Console.WriteLine(stuffs);
// add said element to alreadysaid
}
}
I suggest using HashSet<string> instead of string[] for alreadysaid; now all you have to do is to Add the stuffs:
HashSet<string> alreadysaid = new HashSet<string>() { "Headphones" };
foreach (string stuffs in stuff)
{
if (alreadysaid.Add(stuffs))
{
Console.WriteLine(stuffs);
}
else
{
Console.WriteLine("already said");
}
}
Whenever you want to get alreadysaid as an string[] you can use Linq:
string[] arraySaid = alreadysaid.ToArray();
Use LINQ to do that
int maxIndex = stuff.ToList().IndexOf(stuff.Max());
Related
I have an array of string, I want to take all the string in an interval of this array until string does not contains something.
Something like:
string [] arrayReading = {
"e","x","a","takefromhere",
"keeptaking","keeptaking","dont'ttakefromhere","m","p","l","e"
};
I have tried:
List<string> result = null;
for (int i = 0; i < arrayReading.Length; i++)
{
if (arrayReading[i].Contains("takefromhere"))
{
result.Add(arrayReading[i]);
if (!arrayReading[i + 1].Contains("dont'ttakefromhere"))
{
result.Add(arrayReading[i + 1]);
if (!arrayReading[i + 2].Contains("dont'ttakefromhere"))
{
rescription.Add(arrayReading[i + 1]);
}
}
}
}
Seems working but it's not really dynamic as I want it, because maybe I need to take 20 values between "takefromhere" and "don'ttakefromhere".
When querying you can try Linq:
using System.Linq;
...
List<string> result = arrayReading
.SkipWhile(item => item != "takefromhere")
.TakeWhile(item => item != "dont'ttakefromhere")
.ToList();
Or if you want good old loop solution:
List<string> result = new List<string>();
bool taking = false;
foreach (string item in arrayReading) {
if (!taking)
taking = item == "takefromhere";
if (taking) {
if (item == "dont'ttakefromhere")
break;
result.Add(item);
}
}
Let's have a look:
Console.Write(string.Join("; ", result));
Outcome:
takefromhere; keeptaking; keeptaking
I'm trying to keep score after certain keywords are matched with output from a chatbot. I got it to count a score for every match, but I dont want to match it again if there will be a match with the same keyword. I'm trying to do this by removing the keyword from the list, but it continues to add score.
i.e. I want to add score if chatbot say hi, but only once.
I'm tring this
public void SendQuestionToRobot()
{
if (string.IsNullOrEmpty(inputField.text) == false)
{
string answer = bot.getOutput(inputField.text);
robotOutput.text = answer;
inputField.text = "press enter to type";
List<string> sPattern = new List<string> { "hi", "a painkiller" };
foreach (string s in sPattern)
{
if (Regex.IsMatch(answer, s, RegexOptions.IgnoreCase))
{
controller.score += 5;
sPattern.Remove(s);
break;
}
}
}
}
and
public void SendQuestionToRobot()
{
if (string.IsNullOrEmpty(inputField.text) == false)
{
string answer = bot.getOutput(inputField.text);
robotOutput.text = answer;
inputField.text = "press enter to type";
List<string> sPattern = new List<string> { "hi", "a painkiller" };
foreach (string s in sPattern)
{
if (Regex.IsMatch(answer, s, RegexOptions.IgnoreCase))
{
controller.score += 5;
break;
}
}
foreach (string s in sPattern)
{
if (Regex.IsMatch(answer, s, RegexOptions.IgnoreCase))
{
sPattern.Remove(s);
}
}
}
}
but in both cases the score continues to be added
As is often the case: if you eliminate the loop, you eliminate the chance of writing a buggy loop. Don't write a loop at all!
string match = sPattern.FirstOrDefault(
s => Regex.IsMatch(answer, s, RegexOptions.IgnoreCase));
if (match != null) {
controller.score += 5;
sPattern.Remove(match);
}
No loop; no loop problems.
Don't forget to renew sPattern when needed.
List<string> sPattern = new List<string> { "hi", "a painkiller" };
public void SendQuestionToRobot()
{
if (string.IsNullOrEmpty(inputField.text) == false)
{
string answer = bot.getOutput(inputField.text);
robotOutput.text = answer;
inputField.text = "press enter to type";
foreach (string s in sPattern)
{
if (Regex.IsMatch(answer, s, RegexOptions.IgnoreCase))
{
controller.score += 5;
sPattern.Remove(s);
break;
}
}
}
}
You forgot break in the second foreach. You can't run foreach over collection that you modify inside Foreach!!!! Enumerator allows you only to READ. It becomes not valid after you modify collection.
foreach (string s in sPattern)
{
if (Regex.IsMatch(answer, s, RegexOptions.IgnoreCase))
{
sPattern.Remove(s);
break;
}
}
How would you check multiple RichTextboxes containing multiple lines for unique and or duplicate lines. I've figured out how to loop through the richTextboxes and get the data, but I'm struggling on the logic to see if it's unique. My apologies if code is as clear as mud.
List<string> DistinctItems = new List<string>();
List<string> DupilcatedItems = new List<string>();
List<string> FirstItemsList = new List<string>();
List<string> CompareItemsList = new List<string>();
int ElementIndex = 0;
foreach (RichTextBox c in tableLayoutPanel1.Controls)
{
if (c.Text != null)
{
FirstItemsList.Add(c.Text.Replace("\n", Environment.NewLine).ToString());
if (CompareItemsList.Count == 0)
{
//Have to add the first batch
foreach (string str in FirstItemsList)
{
txtMixerTextBox.AppendText(str);
txtDistinctItems.AppendText(str);
DistinctItems.Add(str);
ElementIndex++;
}
CompareItemsList.Add(c.Text.Replace("\n", Environment.NewLine).ToString());
if (CompareItemsList.Count() > 0)
{
//OK we've gone through the first set
foreach (string s in CompareItemsList)
{
if (DistinctItems.Contains(s))
{
//It's a duplicate see if it's in the duplicate list
if (DupilcatedItems.Contains(s))
{
//OK it's in the list we don't have to add it
//See if it's in the textbox
if (!txtDuplicateItems.Text.Contains(s))
{
//OK it's not in the textbox let's add it
txtDuplicateItems.AppendText(s);
}
}
}
else
{
//It's not there so add it
DupilcatedItems.Add(s);
//now see if it's in the Distinct Textbox
if (!txtDistinctItems.Text.Contains(s))
{
//add it
txtDistinctItems.AppendText(s);
}
txtMixerTextBox.AppendText(s);
}
}
}
}
}
}
Use String.Split.
For example:
foreach (RichTextBox c in tableLayoutPanel1.Controls)
{
if (!c.Text.IsNullOrWhiteSpace)
{
string[] lines = c.Text.Split('\n');
string[] uniqueLines = GetUniqueLines(lines);//Some line-uniqueness checking algorithm
c.Text = String.Join('\n',uniqueLines)
}
}
This is what I did to get the results I was after. Looping through the RichTextboxes as noted above, I wrote the list to a file, stripped out the blank lines (where they came from I haven't the foggiest), read the file into a new list and then got the distinct list from there. I think the blank lines may have been messing me up, or it might have been the fact that I was looping through the strings in the list (again) thus giving myself duplicates. I'll likely get hammered for it, but it worked for me.
List<string> SortingList = new List<string>();
using (StreamReader r = new StreamReader("DistinctItemsNoBlankLines.txt"))
{
string line;
while ((line = r.ReadLine()) != null)
{
SortingList.Add(line);
}
}
List<string>DistinctSortingList = SortingList.Distinct().ToList();
foreach (string str in DistinctSortingList)
{
int index = 0;
while ( index < DistinctSortingList.Count() -1)
{
if (DistinctSortingList[index] == DistinctSortingList[index + 1])
DistinctSortingList.RemoveAt(index);
else
index++;
}
}
txtDistinctItems.Lines = DistinctSortingList.ToArray();
How would like to to compare values in this nested foreach.
I want to compare and if they match print YES for example.
Cheers
using System;
class Program
{
static void Main()
{
// Use a string array to loop over.
string[] ferns =
{
"apple",
"Equisetopsida",
"Marattiopsida",
"Polypodiopsida"
};
string[] fruits=
{
"apple",
"mango",
"Marattiopsida",
"Polypodiopsida"
};
// Loop with the foreach keyword.
foreach (string value in ferns)
{
Console.WriteLine(value);
foreach (string value in fruits)
{
Console.WriteLine(value);
}
//I would like to compare values here.
//Compare frens values against fruits values.
//How can i achieve this
}
}
}
foreach (string fern in ferns)
{
Console.WriteLine(fern);
foreach (string fruit in fruits)
{
Console.WriteLine(fruit);
if(fruit.Equals(fern))
Console.WriteLine("YES");
}
}
value is not a keyword here(through it is in some circumstances). All you have to do is pick whatever variable name you like
Do you want to compare them to see if they match in order? Or just if one list contains the other one at all?
If order counts, loop through both at same time with counter variable (just needs boundary checks):
for (int x = 0; x < ferns.Length; x++)
{
if (ferns[x] == fruits[x])
{
Console.WriteLine("YES!");
}
}
If it just needs to contain it:
foreach (string fern in ferns)
{
if (fruits.Contains(fern))
Console.WriteLine("YES!");
}
This would also be a good place to use an intersection. An intersection takes two lists and returns all the items that 'both' lists have in common.
IEnumerable<string> commonWords = ferns.Intersect(fruits);
Option A
foreach (string fernsvalue in ferns)
{
foreach (string fruitsvalue in fruits)
{
if (fernsvalue.Equals(fruitsvalue))
Console.WriteLine("They are equal");
}
}
Option B
List<string> fernsList = new List<string>(ferns.Length);
List<string> fruitsList = new List<string>(fruits.Length);
fernsList.AddRange(ferns);
fruitsList.AddRange(fruits);
List<string> Differences = fernsList.Except(fruitsList).ToList();
Option C
bool equal = ferns.SequenceEqual(fruits); //compares for exact equality
first of all, in each of yours foreach, current element has this same name, and you will not be able to reach botch of them in second foreach.
To compare two string, you can use String.Compare method. For example:
foreach (string fern in ferns)
{
foreach (string fruit in fruits)
{
if(String.Compare(fern,fruit,false)==0)
{
Console.WriteLine("YES");
}
}
}
Are you trying to see if the elements in the arrays fruits and ferns match at the same index? If so then a nested foreach loop isn't the best way to achieve this. It's much easier to use a for loop
for (int i = 0; i < ferns.Length && i < fruits.Length; i++) {
if (fruits[i] == ferns[i]) {
Console.WriteLine("{0} YES!!!", fruits[i]);
}
}
If instead you're looking to see if there is any match at all for an element in the ferns array in the fruits array then you could try the following
foreach (string fern in ferns) {
Console.Write("{0} ", fern);
bool isMatch = false;
foreach (string fruit in fruits) {
if (fruit == fern) {
isMatch = true;
break;
}
}
Console.WriteLine(isMatch ? "YES" : "NO");
}
I want to get an element of a HashSet only if it contains a specific string in it. i tried
the code below, but i dont get anything... like no matching. but this cant happen cause the UnKnown counter is always 0.
if (!IsbnAuth.Contains(RecTitle))
{
Unknown++;
}
else
{
for (int i = 0; i < IsbnAuth.Count(); i++)
{
if (IsbnAuth.ElementAt(i).Contains(RecTitle))
{
System.Console.WriteLine(IsbnAuth.ElementAt(i));
//isbn = IsbnAuth.ElementAt(i).Substring(0, IsbnAuth.ElementAt(i).IndexOf("\t"));
isbn = IsbnAuth.ElementAt(i).Split(' ')[0];
break;
}
}
}
Any ideas? the problem is not at the RecTitle cause even if it was just a single char instead, the result would be the same.
IsbnAuth is the HashSet.
EDIT: IsbnAuth declaration
HashSet<String> IsbnAuth = new HashSet<String>();
foreach (String line in IsbnAuthors)
{
IsbnAuth.Add(line.Trim());
}
System.Console.WriteLine(IsbnAuth.Count);
This is the first problem:
if (!IsbnAuth.Contains(RecTitle))
{
Unknown++;
}
That checks whether the set contains the whole string, as a complete element. It sounds like it doesn't.
I suspect you really want:
bool found = false;
foreach (String element in IsbnAuth)
{
if (element.Contains(RecTitle))
{
isbn = element.Split(' ')[0];
found = true;
break;
}
}
if (!found)
{
Unknown++;
}
Or even better:
string isbn = IsbnAuth.Where(x => x.Contains(RecTitle))
.Select(x => x.Split(' ')[0])
.FirstOrDefault();
if (isbn == null)
{
Unknown++;
}
It's worth being aware that a HashSet is in a fundamentally unpredictable order - so if there are multiple matches here, you'll end up with an arbitrary result. Is that really what you want?
It seems to me that you are storing mulitple informations held in one string in your Hastable. I would do it in that way:
public class Info
{
public string ISBN { get; set; }
public string Title { get; set; }
}
later in code:
List<Info> isbnAuth = new List<Info>();
foreach (String line in IsbnAuthors)
{
isbnAuth.Add(new Info { ISDN = line.Split(' ')[0], Title = line.Split(' ')[1] });
}
You can search an item like this:
var itemFound = isbnAuth.FirstOrDefault(item => item.Title == RecTitle);
if (itemFound != null)
{
isbn = itemFound.ISBN;
}