Avoid hard-coding all possibilities - c#

I'm making a Xamarin app which has a slider between 1-100. I want it to be so when the slider is at a certain number, the output will do this valueLabel.Text = output; I.e. it will display the contents of the output variable.
output = p1 + p11 + p2
Random r = new Random();
int countLower = r.Next(lower.Count);//I have a list called lower, im getting random values from it
int countLower1 = r.Next(lower.Count);
var p1 = lower[countLower];
var p11 = lower[countLower1];
For example, if the value of the slider (var cat) is 5, I want the output to have 5 things (countLower + countLower1 + countLower2 + countLower3 + countLower4) But i dont know how i can automate the creation of this code based on the slider number. I dont want to hard-code each possibility, is there any way?
I am getting the slider value as such:
public void Slider_ValueChanged(object sender, ValueChangedEventArgs e)
{
var newStep = Math.Round(e.NewValue/step);
var cat =newStep.ToString();
label.Text = cat;
}

Try this:
int output = Enumerable.Range(0, newStep).Select(x => lower[r.Next(lower.Count)]).Sum();

This isn't tested, but the idea is that for each movement on the slider, you generated N random numbers up to the slider value then use String.Join() to bring them all together.
public void Slider_ValueChanged(object sender, ValueChangedEventArgs e)
{
var things = new List<int>();
var newStep = Math.Round(e.NewValue/step);
Random r = new Random();
for (var i = 0; i < newStep; i++) {
things.Add(r.Next(i);
}
var cat = string.Join(",", things);
label.Text = cat;
}

Related

Cant read text file of integers into an integer array

This is driving me literally insane for some reason my code to read a simple text file of ints into an int array wont work.
private void HardButton_Click(object sender, EventArgs e)
{
int[] hard1 = { };
int counter = 0;
using (StreamReader inFile = new StreamReader("h1.txt"))
{
string str = null;
while ((str = inFile.ReadLine()) != null)
{
hard1[counter] = Convert.ToInt32(str);
counter++;
}
}
hard1 is an array of ints that i need to hold each integer placed into it by reading the text file. My error is that my array is out of bounds even though I'm iterating each time through the loop. I am at a loss.
EDIT: Here is the txt file input
0502090
6070203
0502010
5020101
0503010
4020905
0608070
7582391
6478283
8592914
5628191
6573812
4728915
3648271
C#/.Net has real arrays, not the psuedo-array collections you see in so many other languages (it has those, too, it just doesn't try to pass them off as arrays). One attribute of real arrays is a fixed size.
So when you declare the array like this:
int[] hard1 = { };
what you have is an array fixed at size 0, and therefore assigning to the array later on like this:
hard1[counter] = Convert.ToInt32(str);
is assigning to nowhere.
You have many options to fix this. Here is one of them:
private void HardButton_Click(object sender, EventArgs e)
{
var result = File.ReadLines("h1.txt").
Where(line => !string.IsNullOrWhitespace(line)).
Select(line => int.Parse(line)).
ToArray();
}
If you don't know the length in advance... use a list.
private void HardButton_Click(object sender, EventArgs e)
{
var hard1 = new List<int>();
int counter = 0;
using (StreamReader inFile = new StreamReader("h1.txt"))
{
string str = null;
while ((str = inFile.ReadLine()) != null)
{
hard1.Add(Convert.ToInt32(str));
counter++;
}
}
...
If you don't have complete control over the file it might be necessary to do extra controls before converting to int as well.
Is every line exactly one integer?
Do I need to trim?
Can there be empty lines?
Use this:
private void button1_Click(object sender, EventArgs e)
{
int[] hard1 = { };
var lines = File.ReadAllLines("h1.txt");
var lineWithoutEmptySpace = lines.Where(x => !string.IsNullOrEmpty(x)).ToArray();
hard1 = new Int32[lineWithoutEmptySpace.Length];
for (var i = 0; i < lineWithoutEmptySpace.Length; i++)
{
hard1[i] = Convert.ToInt32(lineWithoutEmptySpace[i]);
}
}

find the index of one listbox and reference it in a for loop

I am having a problem in the way I set up a little calorie counter I was trying to do.
I loop through the food items in ListBox2 and find their fat and calorie content per 100g.
I then want to calculate the fat and content for the weight entered in TextBox1 which I have stored in ListBox1. Would anyone be able to help me with this?
protected void btnAdd_Click(object sender, EventArgs e)
{
string foodName = DropDownList1.SelectedValue;
// THIS IS WHERE I ENTER THE WEIGHT OF THE FOOD
string foodWeight = TextBox1.Text;
double Num;
bool isDouble = double.TryParse(foodWeight, out Num);
if (isDouble)
{
ListBox2.Items.Add(foodName);
// I THEN ADD THE WEIGHT TO LISTBOX1
ListBox1.Items.Add(foodWeight);
}
}
protected void btnTest_Click(object sender, EventArgs e)
{
XmlDocument xDoc = new XmlDocument();
xDoc.Load("xml address");
var texts = ListBox2.Items
.Cast<ListItem>()
.Select(item => item.Text)
.ToArray();
var texts2 = ListBox1.Items
.Cast<ListItem>()
.Select(item => item.Text)
.ToArray();
double totalFat = 0;
double totalCalories = 0;
foreach (string i in texts)
{
string fatValue = String.Format("Web_Service/Food[Name='{0}']/Fat", i);
string calorieValue = String.Format("Web_Service/Food[Name='{0}']/Calories", i);
XmlNode fatNode = xDoc.SelectSingleNode(fatValue);
XmlNode calorieNode = xDoc.SelectSingleNode(calorieValue);
// I WANT TO FIND THE WEIGHT AND MULTIPLY IT BY THE FAT AND CALORIE CONTENT
// I was trying something like "weight = ListBox1[i]" or something along those lines
totalFat += double.Parse(fatNode.InnerText) * weight / 100;
totalCalories += double.Parse(calorieNode.InnerText) * weight / 100;
}
Label1.Text = totalFat.ToString();
Label2.Text = totalCalories.ToString();
What I currently have now is in this image: http://imgur.com/ganR0k4. It just doesn't do the final "* weight / 100"
Maybe try and use the ddl.SelectedItem.Text property to find the text associated with whichever item is selected. Or you also have ddl.SelectedItem.Value property which will get you the value of the selected item.

Span Two Columns When Dynamically Adding Controls

I have an ASP.NET web application. This application renders out glossary type items, similar to the following:
This goes through all the letters in the alphabet for items. I am rendering this out and appending it directly to a Controls collection in a Server Control using the following:
List<char> alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray().ToList();
foreach (char c in alpha)
{
Label lblAlphaCharacter = new Label();
lblAlphaCharacter.Font.Size = 24;
lblAlphaCharacter.Font.Bold = true;
lblAlphaCharacter.Text = c.ToString(CultureInfo.InvariantCulture);
Controls.Add(lblAlphaCharacter);
Controls.Add(new LiteralControl("<p>"));
FilterOnAlphaCharacter(this, Page, c);
Controls.Add(new LiteralControl("<p>"));
}
private static void FilterOnAlphaCharacter(Control control, Page page, char character)
{
foreach (List<Things> item in items)
{
string title = item.Title;
string description = item.Definition;
HyperLink link = new HyperLink();
link.Text = title;
control.Controls.Add(link);
Label lblDescription = new Label();
lblDescription.Text = string.Format(" - {0}", description);
control.Controls.Add(lblDescription);
}
}
}
I am trying to, depending on the content, equally split this, so that it looks like this:
This can have different amounts of items. So in reality, there could be 25 entries under "A", and perhaps 1 under "Z". The above is just an example, it goes through all letters A-Z. The expected result would be based on the amount of content, it would equally split between two columns. I have to do this server-side (I was thinking using Table or HtmlTable and related objects).
Howe would you implement a solution for splitting the content equally in a Table or the likes (sort of indifferent on approach).
try this:
//it shows the number of line that inserting during the process
private int _inserteditemCount;
//its number of items in each column
private int _itemsCount;
//line height use for determine paragraph line height
private const string Lineheight = "30px";
protected void Page_Load(object sender, EventArgs e)
{
_inserteditemCount = 0;
var alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
//you can do this query in data access layer
var listCountcount = new Thingsclass().GetThings().Count;
//Count of rows on dictionary + number of leters
_itemsCount = (listCountcount + alpha.Count()) / 2;
var leftdiv = new HtmlGenericControl("div");
var rightdiv = new HtmlGenericControl("div");
//you can change this styles
leftdiv.Style.Add("display", "inline-block");
leftdiv.Style.Add("width", "50%");
leftdiv.Style.Add("float", "Left");
rightdiv.Style.Add("display", "inline-block");
rightdiv.Style.Add("float", "right");
rightdiv.Style.Add("width", "50%");
foreach (var c in alpha)
{
var lblAlphaCharacter = new Label();
lblAlphaCharacter.Font.Size = 24;
lblAlphaCharacter.Font.Bold = true;
lblAlphaCharacter.Text = c.ToString(CultureInfo.InvariantCulture);
var control = _inserteditemCount <= _itemsCount ? leftdiv : rightdiv;
var paragraph = new HtmlGenericControl("p");
paragraph.Style.Add("line-height", Lineheight);
paragraph.Controls.Add(lblAlphaCharacter);
control.Controls.Add(paragraph);
FilterOnAlphaCharacter(leftdiv, rightdiv, c.ToString());
_inserteditemCount++;
}
Panel1.Controls.Add(leftdiv);
Panel1.Controls.Add(rightdiv);
}
private void FilterOnAlphaCharacter(Control leftctr, Control rightctr, string character)
{
//you can do this query in data access layer
var items = new Thingsclass().GetThings().Where(c => c.chara.ToLower().Equals(character.ToLower()));
foreach (var item in items)
{
var paragraph = new HtmlGenericControl("p");
paragraph.Style.Add("line-height", Lineheight);
var control = _inserteditemCount <= _itemsCount ? leftctr : rightctr;
var title = item.Title;
var description = item.Description;
var link = new HyperLink { Text = title };
paragraph.Controls.Add(link);
var lblDescription = new Label { Text = string.Format(" - {0}", description) };
paragraph.Controls.Add(lblDescription);
_inserteditemCount++;
control.Controls.Add(paragraph);
}
}

Return value from method

I am creating calculator with 20 textboxes - 10 for input, 10 for output. After creating a method into which I put parameter(defined in the first 10 textboxes) I return value to main method.
To get all 10 values is it really necessary to write code for all 10 or more text boxes as I have already started or there is smarter way how to pass into the method textbox parameters and return multiple values at once?
UPDATE:
As you recomended I created List of Tuples and used foreach loop to loop through them, but now i get error:
Error 1 Cannot implicitly convert type 'int' to 'string'. Could you help me to point out where the problem is?
private void button1_Click(object sender, EventArgs e)
{
List<Tuple<TextBox,TextBox>> tuple1 = new List<Tuple<TextBox,TextBox>>();
tuple1.Add(Tuple.Create(textBox1, textBox2));
tuple1.Add(Tuple.Create(textBox3, textBox4));
tuple1.Add(Tuple.Create(textBox5, textBox6));
tuple1.Add(Tuple.Create(textBox7, textBox8));
foreach (Tuple<TextBox,TextBox> box in tuple1)
{
var inputBox = box.Item1;
var outputBox = box.Item2;
outputBox.Text = MethodA(Convert.ToInt32(inputBox.Text));
}
}
private int MethodA(int Parameter1)
{
int A = Parameter1;
int B = 20;
int C;
if (A == 16 && B == 20) { C = 15; } else if (A == 20 && B == 20) { C = 25; } else { C = 0; };
return C;
}
You could store all the input-output textbox combination in the constructor:
private List<Tuple<TextBox, TextBox>> textBoxes = new List<Tuple<TextBox, TextBox>>();
public Form1() {
InitializeComponents();
textBoxes.add(Tuple.Create(textBox1, textBox4);
// ...
}
And then, in button1_Click, just iterate over all the textboxes:
foreach (Tuple<TextBox, TextBox> boxes in textBoxes) {
var inputBox = boxes.Item1;
var outputBox = boxes.Item2;
outputBox.Text = MethodA(Convert.ToInt32(inputBox.Text));
}
This might not be the best answer, but it would work:
public class Extensions
{
public MethodA(this TextBox tb)
{
tb.Text = (Convert.ToInt32(tb.Text) + 5).ToString();
}
}
now you can just call:
textBox1.MethodA();
textBox2.MethodA();
...etc.
This isn't necessarily recommended, but it's one way you could simply doing this multiple times.
If you won't be repeating this, it'd probably be better to just inline the logic the same way:
textBox1.Text = (Convert.ToInt32(textBox1.Text) + 5).ToString();
textBox2.Text = (Convert.ToInt32(textBox2.Text) + 5).ToString();
textBox3.Text = (Convert.ToInt32(textBox3.Text) + 5).ToString();

Shuffle string array without duplicates

I am using the Knuth-Fisher-Yates algorithm to display a shuffled array of string items on a windows form. I do not get any duplicates, which is what I was trying to achieve, however, it only spits out 12 of the 13 elements of the array. How can I get it to display all 13 elements of the array? Here is my code:
private void FormBlue1_Load(object sender, EventArgs e)
{
// set the forms borderstyle
this.FormBorderStyle = FormBorderStyle.Fixed3D;
// create array of stationOneParts to display on form
string[] stationOneParts = new string[13];
stationOneParts[0] = "20-packing";
stationOneParts[1] = "5269-stempad";
stationOneParts[2] = "5112-freeze plug";
stationOneParts[3] = "2644-o'ring";
stationOneParts[4] = "5347-stem";
stationOneParts[5] = "4350-top packing";
stationOneParts[6] = "5084-3n1 body";
stationOneParts[7] = "4472-packing washer";
stationOneParts[8] = "3744-vr valve o'ring";
stationOneParts[9] = "2061-packing spring";
stationOneParts[10] = "2037-packing nut";
stationOneParts[11] = "2015-latch ring";
stationOneParts[12] = "stem assembly";
Random parts = new Random();
// loop through stationOneParts using a Swap method to shuffle
labelBlueOne.Text = "\n";
for (int i = stationOneParts.Length - 1; i > 0; i--)
{
int j = parts.Next(i + 1);
Swap(ref stationOneParts[i], ref stationOneParts[j]);
// display in a random order
labelBlueOne.Text += stationOneParts[i] + "\n";
}
}
private void Swap(ref string firstElement, ref string secondElement)
{
string temp = firstElement;
firstElement = secondElement;
secondElement = temp;
}
You don't access the first element.
for (int i = stationOneParts.Length - 1; i >= 0; i--).
As you are showing the texts using the loop that swaps the items, you will not show the last item, because it's never swapped by itself.
Just show the last item after the loop:
labelBlueOne.Text += stationOneParts[0] + "\n";
Alternatively, you can display all the items outside the loop that shuffles them:
for (int i = stationOneParts.Length - 1; i > 0; i--) {
Swap(ref stationOneParts[i], ref stationOneParts[parts.Next(i + 1)]);
}
labelBlueOne.Text = "\n" + String.Join("\n", stationOneParts);
Change your loop condition to i >= 0.
Simpliest approach :
Random rnd = new Random();
var stationOneParts = new List<string>{
"20-packing",
"5269-stempad",
"5112-freeze plug",
"2644-o'ring",
"5347-stem",
"4350-top packing",
"5084-3n1 body",
"4472-packing washer",
"3744-vr valve o'ring",
"2061-packing spring",
"2037-packing nut",
"2015-latch ring",
"stem assembly"}.OrderBy(s => rnd.Next());
labelBlueOne.Text = string.Join(Environment.NewLine, stationOneParts);
Since you mention C# 4.0, why not write is C#-ish?
using System.Linq;
// ...
var stationOneParts = new [] { "20-packing",
"5269-stempad",
"5112-freeze plug",
"2644-o'ring",
"5347-stem",
"4350-top packing",
"5084-3n1 body",
"4472-packing washer",
"3744-vr valve o'ring",
"2061-packing spring",
"2037-packing nut",
"2015-latch ring",
"stem assembly" };
Random rand = new Random();
stationOneParts = stationOneParts
.Distinct() // see subject: '... without duplicates'
.Select(i => new { i, key=rand.Next() })
.OrderBy(p => p.key)
.Select(p => p.i)
.ToArray();

Categories