I have the following enum declared:
public enum EtcMethod
{
ACCORD,
COROLLA,
COROLLA_S,
CAMRY,
CIVIC
}
On my form, I have a handful of controls with their Tag property set:
myControl1.Tag = "ACCORD";
myControl2.Tag = "COROLLA";
myControl3.Tag = "CIVIC COROLLA_S CAMRY";
Then I'm checking the controls' tags in a loop to see if any of the values are found:
private void HideControls(EtcMethod etcMethod, LayoutControlGroup lcg)
{
foreach (BaseLayoutItem ctl in lcg.Items)
{
if (ctl.GetType() == typeof (LayoutControlItem))
{
LayoutControlItem item = (LayoutControlItem)ctl;
if (item.Tag.ToString().IndexOf(etcMethod.ToString()) >= 0)
item.Visibility = LayoutVisibility.Always;
else
item.Visibility = LayoutVisibility.Never;
}
}
}
But the problem with this is, for example, if etcMethod is COROLLA and item.Tag.ToString() is "COROLLA_S" that'll erroneously pass the check.
How can I make sure that it'll find an exact match instead of a "partial" match? In other words, I would like it to behave as if you checked off the "Match whole word" option using Visual Studio's Find feature.
The only solution I could think of would be to check the value of the character at etcMethod.Lenght+1 and see if it's a space (indicating the beginning of another enum value) or if that position even exists (indicating the end of the tag), but that seems particularly sloppy.
Why don't you Split it and use Contains ?
if (item.Tag.ToString().Split().Contains(etcMethod.ToString()))
This will first split your Tag on space, if it hasn't space it just turn it into a string array, then using Contains on array will look for exact match.
This may be one solution:
if (item.Tag.ToString() + " ").IndexOf(etcMethod.ToString() + " ") >= 0)
Related
I'm making a game with character attributes, like strength, agility, etc. I have them all in a <string, double> dictionary. I need to implement "mods" to attributes from equipment, buffs, etc. I'd like to replace all instances of "CurrentStats[Key]" with a function(string input) of some sort, via Find/Replace. (I have HUNDREDS of references to it, I can't do that all by hand)
So basically, I'm looking for a way to write a function where I can somehow write
Function("Strength") = 5; for assignment
while still being able to use
if(Function("Strength") == 5) for fetching.
Is this possible?
Visual Studio has inbuilt regular expressions in its search and replace. You just need to enable the option when doing your replace.
You can probably just perform a global search and replace of something like CurrentStats\[([^\]]+)\] to MyFunction($1).
Explanation: this searches for the literal string CurrentStats[], with the content between the two brackets being a group (referenced in the replace as $1), indicated by having it surrounded by ( and ), containing [^\]]+, or, "a character group of anything that's not the closing quote ], repeated one or more times".
Note that this won't work if the key itself could contains something like myArray[i] since then it'll obviously match the closing bracket of that. Regex isn't really good at doing matching brackets or tags.
The locigcal approach would be to have a class for your character. You can use properties. Functions are usually called with arguments if you want to assign something, but properties can be assigned directly.
public class Character {
private bool overpowered = false;
private int _strength = 0;
public int Strength
{
get { return this._strength; }
set {
if (value > 10) { overpowered = true; }
this._strength = value;
}
}
// [...]
}
Then to use the property simple access it via the object:
Character c = new Character();
c.Strength = 5;
if (c.Strength == 5) { /* ... */ }
Using a dictionary makes little sense here.
It looks like ref returns are what I was after. I don't know how to mark this as answered. First post here. Thanks everyone
When I initialize a combobox with text contents like so, where eo is some object with a ToString() override:
foreach (EncodingInfo ei in Encoding.GetEncodings()) {
Encoding e = ei.GetEncoding();
encodeObject eo = new encodeObject();
eo.Name = ei.DisplayName;
eo.Value = ei.Name;
int targetIndex = this.targetEncodingBox.Items.Add(eo);
}
I can set this to be the default value by using
this.targetEncodingBox.SelectedIndex = targetIndex
However, when the box is actually sorted, and the data initially entered into the box using the Add() method is not sorted, the default index is kept while the box is re-sorted, resulting in an entirely different value being selected almost all of the time.
A basic solution for this is to look up the generated value that the combobox would display and use FindStringExact:
this.targetEncodingBox.SelectedIndex = this.targetEncodingBox.FindStringExact("utf-8 -- Unicode (utf-8)");
However, this results in other problems. The string in question may depend on the user's operating system' language settings in this particular case. This can't be known beforehand.
Thus another way I've found is to manually find the name of the encoding a second time and set the SelectedIndex after the box is fully populated, using the same convention for concatenating the acronym name and translated name as used in the definition for encodeObject.ToString();.
foreach (EncodingInfo ei in Encoding.GetEncodings()) {
if (ei.Name == "utf-8") {
this.sourceEncodingBox.SelectedIndex = this.sourceEncodingBox.FindStringExact(ei.Name + " -- " + ei.DisplayName);
}
}
Note: the definition of the class encodeObject below:
private class encodeObject {
public string Name;
public string Value;
public override string ToString() {
return Value + " -- " + Name;
}
}
This actually works, and does exactly what I want, yet the solution seems quite clunky to do something that should really be a single call. Is there a better way of achieving this?
As Hans commented you need to create that list and store it to a variable.
Since the available encodings are unlikely to change anyway, this should happen in some class constructor or when you load your settings.
This variable then can be re-used anywhere you need it, it also can be easily updated & sorted as you like.
After this step the rest is trivial, create a variable with a default value/index, and once a ComboBox was assigned this list just set the SelectedValue/SelectedIndex value to your default value/index.
`private void Dot_Click_1(object sender, EventArgs e)
{
if (NumBox1.Text.IndexOfAny(char['.'])
{
}`
I think the solution for the restriction of one decimal point is here.
if (!string.IsNullOrEmpty(NumBox1.Text)
{
numbox1.text = "0" + ".";
}
}
this is when the textbox is empty. Then I clicked dot sign to get automatically a result of "0." inside the textbox. But, it only returns "."
It's not clear why you've got char['.'] at all, or what you expect it to mean. I suspect you just want the character literal '.' and use IndexOf.
else if (NumBox1.Text.IndexOf('.') == -1 && ...)
You only want to use IndexOfAny if you're looking for multiple things, in which case you'd want something like:
IndexOfAny(new[] { '.', ',' })
Or even more simply:
else if (!NumBox1.Text.Contains(".") && ...)
I strongly suspect that your conditions really aren't what you want - basically at the moment you'll always set the textbox value to "0." if you don't have a dot (ignoring any previous input), and NumBox1.Text will never be null - but you need to work through that for yourself.
EDIT: Using a single call to IndexOf isn't going to tell you if there's more than one occurrence of .. One simple way to do that is:
if (text.IndexOf('.') != text.LastIndexOf('.'))
{
...
}
Please note, the 'C#' tag was included intentionally, because I could accept C# syntax for my answer here, as I have the option of doing this both client-side and server-side. Read the 'Things You May Want To Know' section below. Also, the 'regex' tag was included because there is a strong possibility that the use of regular expressions is the best approach to this problem.
I have the following highlight Plug-In found here:
http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html
And here is the code in that plug-in:
/*
highlight v4
Highlights arbitrary terms.
<http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html>
MIT license.
Johann Burkard
<http://johannburkard.de>
<mailto:jb#eaio.com>
*/
jQuery.fn.highlight = function(pat) {
function innerHighlight(node, pat) {
var skip = 0;
if (node.nodeType == 3) {
var pos = node.data.toUpperCase().indexOf(pat);
if (pos >= 0) {
var spannode = document.createElement('span');
spannode.className = 'highlight';
var middlebit = node.splitText(pos);
var endbit = middlebit.splitText(pat.length);
var middleclone = middlebit.cloneNode(true);
spannode.appendChild(middleclone);
middlebit.parentNode.replaceChild(spannode, middlebit);
skip = 1;
}
}
else if (node.nodeType == 1 && node.childNodes && !/(script|style)/i.test(node.tagName)) {
for (var i = 0; i < node.childNodes.length; ++i) {
i += innerHighlight(node.childNodes[i], pat);
}
}
return skip;
}
return this.length && pat && pat.length ? this.each(function() {
innerHighlight(this, pat.toUpperCase());
}) : this;
};
jQuery.fn.removeHighlight = function() {
return this.find("span.highlight").each(function() {
this.parentNode.firstChild.nodeName;
with (this.parentNode) {
replaceChild(this.firstChild, this);
normalize();
}
}).end();
};
This plug-in works pretty easily.
If I wanted to highlight all instances of the word "Farm" within the following element...(cont.)
<div id="#myDiv">Farmers farm at Farmer's Market</div>
...(cont.) all I would need to do is use:
$("#myDiv").highlight("farm");
And then it would highlight the first four characters in "Farmers" and "Farmer's", as well as the entire word "farm" within the div#myDiv
No problem there, but I would like it to use this:
$("#myDiv").highlight("Farmers");
And have it highlight both "Farmers" AND "Farmer's". The problem is, of course, that I don't know the value of the search term (The term "Farmers" in this example) at runtime. So I would need to detect all possibilities of no more than one apostrophe at each index of the string. For instance, if I called $("#myDiv").highlight("Farmers"); like in my code example above, I would also need to highlight each instance of the original string, plus:
'Farmers
F'armers
Fa'rmers
Far'mers
Farm'ers
Farme'rs
Farmer's
Farmers'
Instances where two or more apostrophes are found sid-by-side, like "Fa''rmers" should, of course, not be highlighted.
I suppose it would be nice if I could include (to be highlighted) words like "Fa'rmer's", but I won't push my luck, and I would be doing well just to get matches like those found in my bulleted list above, where only one apostrophe appears in the string, at all.
I thought about regex, but I don't know the syntax that well, not to mention that I don't think I could do anything with a true/false return value.
Is there anyway to accomplish what I need here?
Things You May Want To Know:
The highlight plug-in takes care of all the case insensitive requirements I need, so no need to worry about that, at all.
Syntax provided in JavaScript, jQuery, or even C# is acceptable, considering the hidden input fields I use the values from, client-side, are populated, server-side, with my C# code.
The C# code that populates the hidden input fields uses Razor (i.e., I am in a C#.Net Web-Pages w/ WebMatrix environment. This code is very simple, however, and looks like this:
for (var n = 0; n < searchTermsArray.Length; n++)
{
<input class="highlightTerm" type="hidden" value="#searchTermsArray[n]" />
}
I'm copying this answer from your earlier question.
I think after reading the comments on the other answers, I've figured out what it is you're going for. You don't need a single regex that can do this for any possible input, you already have input, and you need to build a regex that matches it and its variations. What you need to do is this. To be clear, since you misinterpreted in your question, the following syntax is actually in JavaScript.
var re = new RegExp("'?" + "farmers".split("").join("'?") + "'?", "i")
What this does is take your input string, "farmers" and split it into a list of the individual characters.
"farmers".split("") == [ 'f', 'a', 'r', 'm', 'e', 'r', 's' ]
It then stitches the characters back together again with "'?" between them. In a regular expression, this means that the ' character will be optional. I add the same particle to the beginning and end of the expression to match at the beginning and end of the string as well.
This will create a regex that matches in the way you're describing, provided it's OK that it also matches the original string.
In this case, the above line builds this regex:
/'?f'?a'?r'?m'?e'?r'?s'?/
EDIT
After looking at this a bit, and the function you're using, I think your best bet will be to modify the highlight function to use a regex instead of a straight string replacement. I don't think it'll even be that hard to deal with. Here's a completely untested stab at it.
function innerHighlight(node, pat) {
var skip = 0;
if (node.nodeType == 3) {
var matchResult = pat.exec(node.data); // exec the regex instead of toUpperCase-ing the string
var pos = matchResult !== null ? matchResult.index : -1; // index is the location of where the matching text is found
if (pos >= 0) {
var spannode = document.createElement('span');
spannode.className = 'highlight';
var middlebit = node.splitText(pos);
var endbit = middlebit.splitText(matchResult[0].length); // matchResult[0] is the last matching characters.
var middleclone = middlebit.cloneNode(true);
spannode.appendChild(middleclone);
middlebit.parentNode.replaceChild(spannode, middlebit);
skip = 1;
}
}
else if (node.nodeType == 1 && node.childNodes && !/(script|style)/i.test(node.tagName)) {
for (var i = 0; i < node.childNodes.length; ++i) {
i += innerHighlight(node.childNodes[i], pat);
}
}
return skip;
}
What I'm attempting to do here is keep the existing logic, but use the Regex that I built to do the finding and splitting of the string. Note that I'm not doing the toUpper call anymore, but that I've made the regex case insensitive instead. As noted, I didn't test this at all, but it seems like it should be pretty close to a working solution. Enough to get you started anyway.
Note that this won't get you your hidden fields. I'm not sure what you need those for, but this will (if it's right) take care of highlighting the string.
I’m working on a self directed simple program to practice concepts I’ve learned thus far. My project is related to chess, in this case specifically the board (columns a-h and rows 1-8). The user is asked for the current location of a specific chess piece hopefully entered as a letter for the column followed by a number for the row.
To validate this it made sense to me to first check if this value was entered as a string of two characters, otherwise what is entered is already incorrect.
I then converted the entered string to lower case characters before comparing it with my list of acceptable array elements.
From searching this site I get the impression that a string stores its characters as an array and using the char property of string you would be able to pull off the first character thus comparing char to char. I have not yet found anything specific enough in my searches to really give me a good understanding of what is happening. This is the closest option I’ve come across which I didn’t feel was applicable to this case. Any insight would be appreciated.
The code that follows produces the following error.
Operator ‘==’ cannot be applied to operands of type ‘char’ and
‘string’
private char[] gridColumns = new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', };
private void createMoveButton_Click(object sender, RoutedEventArgs e)
{
// Assigns text box input to associated private fields
this.gameId = this.gameIdTextBox.Text;
this.playerId = this.playerIdTextBox.Text;
this.gamePiece = this.gamePieceTextBox.Text;
this.currentLocation = this.currentLocationTextBox.Text;
this.targetLocation = this.targetLocationTextBox.Text;
// Current location should only ever be 2 characters, ensure from the start this is true.
if (currentLocationTextBox.Text.Length == 2)
{
// Converts contents of currentLocationTextBox to lower case characters for comparison.
string cl = currentLocation.ToLowerInvariant();
// Iterates through my array of possible column choices
for (int i = 0; i < gridColumns.Length; i++)
{
Char.ToLowerInvariant(currentLocationTextBox.Text[0]);
// Trying to compare the first character of my string to the char element of my array.
if (cl[0] == gridColumns[i])
{
//TODO
}
}
}
else
{
MessageBox.Show("Check your starting location. It needs to be a lower case character variable (a-h) followed by a number (1-8)");
}
}
Unlike C, a string and an array of char are different. A string in C# can be viewed as an array of char but you should consider them different, therefore the '==' comparison isn't appropriate. One easy way to see this is with the following simple expression
if ("a" == 'a') { /* do something */ } // ERROR!
It looks like it should work but it generates the same error you are seeing, because it is trying to compare the string "a" to the char 'a'. In your example code the Text property of your textbox control is of type string.
The string class has an indexer that allows you to treat a string as an array of char, but it's usually better (simpler) to use one of the many string methods to accomplish your goal. Consider this:
var gridcolumns = "abcdefgh";
var gridrows = "12345678";
var input = "a1"; // column row
var col = gridcolumns.IndexOf(input[0]); // 0 -7
var row = gridrows.IndexOf(input[1]); // 0 -7
In the code you gave I don't see a line that would generate the error you provided. The following line serves no purpose
Char.ToLowerInvariant(currentLocationTextBox.Text[0]);
Because you are not assigning the returned value to a variable, plus 'cl' already contains the lowercasing of that particular value.
This line
if (cl[0] == gridColumns[i])
should not generate the error because both items are of type char.
Dweeberly's answer when applied... and shortened:
Answer: Change the single quotes to double-quotes.
My reasoning:
Assume the following code:
string IAmAString;
// set string to anything
IAmAString = "Q";
if (IAmAString == 'Q')
{
// do something, but never gets here because "Q" is a string, and 'Q' is a char
// Intellisense gives error on the if statement of
//
// "Operator '==' cannot be applied to operands of types 'string' and 'char'"
//
// because C# is a strongly typed language, and the '==' is not by
// default (in VS2012) overloaded to compare these two different types.
// You are trying to compare a string with something that
// is not-string, and C# is trying to let you know
// that that is not going to work.
}
It is fixed by changing the quotes to double-quotes. C# definitely seems to consider single quotes around a single character to be Char, and not string.
just change the quotes within the if statement:
IAmAString = "Q";
if (IAmAString == "Q")
{
// does whatever is here within reason; "Q" is a string and "Q" is a string
}
At least this worked for me, and that's my 'quick' (where 'q' != "q") explanation of why.
Getting back to work...
Try to use this comparison:
(cl.ToCharArray())[0] == gridColumns[i]
I ran your program and it works fine. I think problem is some place else.
Looping through the array just to see if an element is contained in it is kind of overkill when an array has a .Contains method. Something like this without the for loop should work:
if (gridColumns.Contains(cl[0]))
{
//TODO
}
if(char[0].ToString() == "!") print("do something");