Displaying Multiple Arrays - c#

I have a project where I have to take in input of names, weights, and heights and put them into arrays and display them into a TextBox like this
name = "..."
weight = "..."
height= "..."
I have been able to populate my arrays but I do not understand how to it output it like the example above. Currently my output is all names, THEN all weights then all heights. Could someone explain how I would be able to make it display like the example? The code I have so far is
private void ShowButton_Click(object sender, EventArgs e)
{
txtShow.Text += string.Join(System.Environment.NewLine, nameArray);
txtShow.Text += string.Join(System.Environment.NewLine, weightArray);
txtShow.Text += string.Join(System.Environment.NewLine, heightArray);
}
private void AddButton_Click(object sender, EventArgs e)
{
if (this.index < 10)
{
nameArray[this.index] = nameBox.Text;
weightArray[this.index] = double.Parse(weightBox.Text);
heightArray[this.index] = double.Parse(heightBox.Text);
this.index++;
}
}
The array can store up to 10 values and I am required to use arrays and not lists.

You Should::::: Lots of ways to optimize what you're trying to do, but this is homework and you don't want to look like you're the world's greatest programmer -- you want to do the project like the prof is expecting you to. So creating classes and joining lists is not part of your particular solution set. Try:
PS - on first answer, I tried to keep my suggestion code as close to yours as possible - to answer your question without changing your code. Another commenter suggested that contantly updating a textbox.Text will lead to blinking issues. If that happens to you, I'd suggest using a temporary string as I've edited my text to do.
I know this is homework - so I'm not suggesting any grand optimizations that will make you look like you've been getting your homework done at SO.
EDIT You've asked for a way to detect empty. Based on my understanding of your code and keeping it simple, try:
private void AddButton_Click(object sender, EventArgs e)
{
if (this.index < 10)
{
if(nameBox.Text.Length==0||weightBox.Text.Length==0||heightBox.Text.Length==0){
MessageBox.Show("You must enter a name, weight, and height!");
}else{
nameArray[this.index] = nameBox.Text;
weightArray[this.index] = double.Parse(weightBox.Text);
heightArray[this.index] = double.Parse(heightBox.Text);
this.index++;
nameBox.Text = "";
weightBox.Text = "";
heightBox.Text = "";
}
}
}
private void ShowButton_Click(object sender, EventArgs e)
{ string myString = "";
for(int i=0;i<nameArray.Length;i++)
{
myString+= "Name: "+nameArray[i]+", ";
myString += "Weight: "+weightArray[i]+", ";
myString += "Height: "+heightArray[i]+"\n");
}
txtShow.Text = myString;
}
NOTE Textboxes have validation methods which will do the work of my IF/THEN statement in my revised edit to find empties. If you think the prof is looking for form (control) validation instead of codebehind IF/THEN, let me know and I'll help with that.
Okay - you mentioned the need to sort. To do that, we need to use some way of grouping the input data. We could use Dictionary or class. Let's go with class:
Putting it all together: Have a look at this potential solution - if you think it's too complicated for what your homework should look like, we can try to simplify. Let me know:
public class Person{
public string Name {get;set;}
public double Height {get;set;}
public double Weight {get; set;}
public string Print(){
return "Name: "+Name+", Height: "+Height.ToString()+", Weight: "+Weight.ToString()+"\r\n";
}
}
Person[] People = new Person[10];
int thisIndex = 0;
private void AddButton_Click(object sender, EventArgs e)
{
if (this.index < 10)
{
if(nameBox.Text.Length==0||weightBox.Text.Length==0||heightBox.Text.Length==0)
{
MessageBox.Show("You must enter a name, weight, and height!");
}else{
Person p = new Person();
p.Name = nameBox.Text;
p.Weight = double.Parse(weightBox.Text);
p.Height = double.Parse(heightBox.Text);
People[thisIndex] = p;
thisIndex++;
nameBox.Text = "";
weightBox.Text = "";
heightBox.Text = "";
}
}
}
private void ShowButton_Click(object sender, EventArgs e)
{
People = People.OrderBy(p=>p.Name).ToArray();
string myString = "";
for(int i=0;i<10;i++)
{
if(People[I]!=null){
myString+= People[I].Print();
}
}
txtShow.Text = myString;
}

You should create a class for this purpose. A class enables you to create your own custom types by grouping together variables of three types (string,double and double):
public class Person
{
public string Name { get; set; }
public double Weight { get; set; }
public double Height { get; set; }
public override string ToString()
{
return Name + " " + Weight + " " + Height;
}
}
Then:
Person[] persons = new Person[10];
private void AddButton_Click(object sender, EventArgs e)
{
persons[index] = new Person
{
Name = nameBox.Text,
Weight = double.Parse(weightBox.Text),
Height = double.Parse(heightBox.Text)
};
index++;
}
And finally (look at the ShowButton's code that now is one line):
txtShow.Text += string.Join(System.Environment.NewLine, persons.AsEnumerable());

Linq solution:
private void ShowButton_Click(object sender, EventArgs e) {
int n = Math.Min(Math.Min(nameArray.Length, weightArray.Length), heightArray.Length));
txtShow.Text = String.Join(Environment.NewLine, Enumerable
.Range(0, n)
.Select(i => string.Format("Name: {0}, Weight: {1}, Height: {2}",
nameArray[i], weightArray[i], heightArray[i])));
}
Try avoiding txtShow.Text += fragments, especially in loops (each Textchanging means redrawing and thus blinking)

Related

I want to randomly select one of the methods I created before [duplicate]

This question already exists:
I want to randomly select one of the methods I created before when I clicked [closed]
Closed 3 years ago.
I want to randomly select one of the methods I created before when I clicked
if I can't tell you exactly what I want to say, I'm sorry for my bad English
enter code here
public void s1()
{
textBox1.Text = "ali9090";
textBox2.Text = "bar123";
}
public void s2()
{
textBox1.Text = "ali777";
textBox2.Text = "BKardak123";
}
private void button4_Click(object sender, EventArgs e)
{
Random rastgele = new Random();
rastgele.Next(s1(),s2());
}
I know my code is ridiculous, but I'd appreciate it if you told me how to do what I wanted.
You can put the methods into a collection of Action objects. Something like:
var methods = new List<Action> { () => s1(), () => s2() };
As long as your methods have the same signature, that is. (If they don't then you can wrap them in Action<> or Func<> objects that do, but the bigger question is how you plan to dynamically use methods with different signatures. So for now I'll assume they're the same.)
Then you can randomly select an element from that list like any other list and invoke it like a method:
var rastgele = new Random();
var next = rastgele.Next(methods.Count);
methods[next]();
As an aside (suggested in a comment below), it's likely that you'll want to retain the same Random instance for better randomness over time. Perhaps by placing it at the class level. Something like this:
private Random rastgele = new Random();
private void button4_Click(object sender, EventArgs e)
{
var methods = new List<Action> { () => s1(), () => s2() };
var next = rastgele.Next(methods.Count);
methods[next]();
}
The time between clicks may be making the randomness appear to work well, and for a small enough sample set it's likely to never be a problem. But it's best to get into the habit of keeping a single randomizer as it can become a source of bugs when multiple randomizers are used in rapid succession with the same seed.
The above answer is very well but if you want to implement in a simple way, you can use switch case (or if/else) like below.
private void button4_Click(object sender, EventArgs e)
{
Random rastgele = new Random();
int randomNum = rastgele.Next(1,3);
switch (randomNum)
{
case 1:
s1(); break;
case 2:
s2(); break;
}
}
Here is a solution using an Attribute to have an on-the-fly automatic management of the methods list:
using System.Reflection;
public partial class FormTest : Form
{
private List<MethodInfo> RandomMethods = new List<MethodInfo>();
private Random Random = new Random();
public FormTest()
{
InitializeComponent();
InitializeRandomMethods();
}
private void InitializeRandomMethods()
{
foreach ( var method in this.GetType().GetMethods() )
foreach ( var attribute in method.GetCustomAttributes(false) )
if ( attribute is RandomMethodAttribute )
if ( method.ReturnType != typeof(void) || method.GetParameters().Length != 0 )
{
string strError = $"Bad method signature: {GetType().Name}.{method.Name}"
+ Environment.NewLine
+ "Must have no return type and no parameters.";
MessageBox.Show(strError, Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
RandomMethods.Add(method);
}
[RandomMethod]
public void s1()
{
textBox1.Text = "ali9090";
textBox2.Text = "bar123";
}
[RandomMethod]
public void s2()
{
textBox1.Text = "ali777";
textBox2.Text = "BKardak123";
}
private void button4_Click(object sender, EventArgs e)
{
if (RandomMethods.Count > 0)
RandomMethods[Random.Next(RandomMethods.Count)].Invoke(this, null);
else
{
string strWarning = "No random method available.";
MessageBox.Show(strWarning, Text, MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
}
After the form class code or in another file:
public class RandomMethodAttribute : Attribute
{
public RandomMethodAttribute()
{
}
}

Need to sort words in an array using a separate method

Question:
Write a program named SortWords that includes a method that accepts any number of words and sorts them in alphabetical order. Demonstrate that the program works correctly when the method is called with one, two, five, or ten words.
What I have thus far:
private void button1_Click(object sender, EventArgs e)
{
String[] outWords = new string[20];
outWords[0] = textbox1.Text;
outWords[1] = textBox2.Text;
outWords[2] = textBox3.Text;
outWords[3] = textBox4.Text;
outWords[4] = textBox5.Text;
outWords[5] = textBox6.Text;
outWords[6] = textBox7.Text;
outWords[7] = textBox8.Text;
outWords[8] = textBox9.Text;
outWords[9] = textBox10.Text;
sortAndPrint(outWords[11]);
}
private void sortAndPrint(params string[] newWords)
{
Array.Sort(newWords);
label1.Text = newWords[0];
label2.Text = newWords[1];
label3.Text = newWords[2];
label4.Text = newWords[3];
label5.Text = newWords[4];
label6.Text = newWords[5];
label7.Text = newWords[6];
label8.Text = newWords[7];
label9.Text = newWords[8];
label10.Text = newWords[9];
}
My issues here is that I either don't get anything in my label boxes or I get errors thrown from can't convert a string into string[] or System.IndexOutOfRangeException. I'm sure im doing something completely wrong here.
Try this :
private void button1_Click(object sender, EventArgs e)
{
string[] outWords = new string[10];
outWords[0] = textbox1.Text;
outWords[1] = textBox2.Text;
outWords[2] = textBox3.Text;
outWords[3] = textBox4.Text;
outWords[4] = textBox5.Text;
outWords[5] = textBox6.Text;
outWords[6] = textBox7.Text;
outWords[7] = textBox8.Text;
outWords[8] = textBox9.Text;
outWords[9] = textBox10.Text;
sortAndPrint(outWords);
}
private void sortAndPrint(string[] newWords)
{
Array.Sort(newWords);
label1.Text = newWords[0];
label2.Text = newWords[1];
label3.Text = newWords[2];
label4.Text = newWords[3];
label5.Text = newWords[4];
label6.Text = newWords[5];
label7.Text = newWords[6];
label8.Text = newWords[7];
label9.Text = newWords[8];
label10.Text = newWords[9];
}
Summary
Pass whole array sortAndPrint(outWords); not single element.
Take array length only what you need. string[] outWords = new string[10];
Please check this question for the use of params. You need to pass values when you user param but if you need to pass variable, you have to remove params.
Example of params
private void button1_Click(object sender, EventArgs e)
{
sortAndPrint("one","two","three","four","five");
}
private void sortAndPrint(params string[] newWords)
{
Array.Sort(newWords);
label1.Text = newWords[0];
label2.Text = newWords[1];
label3.Text = newWords[2];
label4.Text = newWords[3];
label5.Text = newWords[4];
}
sortAndPrint(outWords[11]);
will pass a single string (as an array) to sortAndPrint, so when you call
label2.Text = newWords[1];
you get an out of bounds exception. Try just
sortAndPrint(outWords);
to pass the entire array. Also note that empty slots in the array wil get sorted before other strings, so you need to come up with a way to get rid of the blank/null string.
Or, if the intent is to demonstrate how to use params, you could do something like:
sortAndPrint(textbox1.Text,
textbox2.Text,
textbox3.Text,
textbox4.Text,
textbox5.Text);
But you need to check the bounds of the array in sortAndPrint, rather than just assuming the array has a size of at least 10.
If you read the instructions carefully, you have this requirement:
...includes a method that accepts any number of words...
You accomplish this by using the params keyword along with a string[].
...and sorts them in alphabetical order.
This part you doing with Array.Sort(newWords);
Demonstrate that the program works correctly when the method is called with one, two, five, or ten words
This part you're not doing - you're assuming in your code that the input array will have 10 items, when instead you should check to see how many items it has before outputting the results.
Since the array size cannot be determined by the method, then it cannot make any assumption that there will be enough labels on the form to populate with the results. Given this, we could use a MessageBox to show the results instead, and we can use String.Join to join all the items in the array with an Environment.NewLine character in order to show the sorted words in different lines:
private void SortAndPrint(params string[] newWords)
{
Array.Sort(newWords);
MessageBox.Show(string.Join(Environment.NewLine, newWords));
}
Now, we can demonstrate the use of this function by passing in different numbers of arguments to it.
First, just so we're on the same page, I have this code in the Form_Load method that adds 10 textboxes to the form, all with the tag "input":
private void Form1_Load(object sender, EventArgs e)
{
var stdHeight = 20;
var stdWidth = 100;
var stdPad = 10;
var count = 10;
for (int i = 0; i < count; i++)
{
var textBox = new TextBox
{
Name = "textBox" + (i + 1),
Left = stdPad,
Width = stdWidth,
Height = stdHeight,
Top = (stdHeight + stdPad) * i + stdPad,
Tag = "input"
};
Controls.Add(textBox);
}
}
Now, in our button click event, we can search for all controls on the form who have the Tag == "input" and whose .Text property is not empty, and we can pass these Text values to our method both as a single array OR as individual items:
private void button1_Click(object sender, EventArgs e)
{
// Select all textbox Text fields that have some value
var words = Controls.Cast<Control>()
.Where(t => t.Tag == "input" && !string.IsNullOrWhiteSpace(t.Text))
.Select(t => t.Text)
.ToArray();
// Pass all the words in a single array to our method
SortAndPrint(words);
// We can also demonstrate this by passing individual words
// Pass one word if we can
if (words.Length > 0)
{
SortAndPrint(words[0]);
}
// Pass two words if we can
if (words.Length > 1)
{
SortAndPrint(words[0], words[1]);
}
// Pass five words if we can
if (words.Length > 4)
{
SortAndPrint(words[0], words[1], words[2], words[3], words[4]);
}
// Pass ten words if we can
if (words.Length > 9)
{
SortAndPrint(words[0], words[1], words[2], words[3], words[4],
words[5], words[6], words[7], words[8], words[9]);
}
}

C# insert text after each occurence of a text string using wildcards [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
Solved:
This solution has been solved. I was modding a game and am creating a C# windows form to easily manipulate large quantities of repeating data, or expressions, and quickly insert mass changes to a file, or files. I was stuck on identifying a regular expression with Regex in my data files and inserting a text box field of data right after the expression I identified. The expression I have works in the regex editor, thanks to #Kris, but when I deployed it into my program, nothing happened. I apologize for not having my thoughts in order, I will be sure to be more clear next time I use SO.
Below is the data I wanted to manipulate, followed by the working code I was able to fix myself with pointers from #Kris and #Rufus L. Again, I needed to search for particular data strings and insert a new string underneath the data property in every occurrence in the file. Hope this helps someone.
The data properties text looks like this:
1234 = {
workers = {
culture = dudes
religion = awesome
size = 37800
}
professionals = {
culture = dudes
religion = awesome
size = 6000
}
leaders = {
culture = dudes
religion = awesome
size = 500
}
}
1235 = {
workers = {
culture = dudes
religion = awesome
size = 37800
}
professionals = {
culture = dudes
religion = awesome
size = 6000
}
leaders = {
culture = dudes
religion = awesome
size = 500
}
}
I only want to insert text into the parent #### = {} property that holds the child = {} property fields. IE, I want to insert textBox2.Text in a new line under 1234 = {
I have the regex expression linked on here, thanks to #Kris.
namespace WindowsFormsApplication1 {
public partial class Form1 : Form {
static string[] files;
static int curNum = 0;
static string[] txtFiles;
static string[] provinces;
public Form1() {
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e) {
System.IO.File.WriteAllText(pathText.Text + txtFiles[curNum], richTextBox1.Text);
}
private void prevButton_Click(object sender, EventArgs e) {
if(curNum > 0)
curNum--;
richTextBox1.Text = System.IO.File.ReadAllText(pathText.Text + txtFiles[curNum]);
filenameLabel.Text = txtFiles[curNum];
}
private void loadButton_Click(object sender, EventArgs e) {
curNum = 0;
txtFiles = GetFileNames(pathText.Text, "*.txt");
richTextBox1.Text = System.IO.File.ReadAllText(pathText.Text + txtFiles[curNum]);
filenameLabel.Text = txtFiles[curNum];
}
static string[] GetFileNames(string path, string filter) {
files = Directory.GetFiles(path, filter);
for (int i = 0; i < files.Length; i++)
files[i] = Path.GetFileName(files[i]);
return files;
}
private void nextButton_Click(object sender, EventArgs e) {
if(curNum < txtFiles.Length)
curNum++;
richTextBox1.Text = System.IO.File.ReadAllText(pathText.Text + txtFiles[curNum]);
filenameLabel.Text = txtFiles[curNum];
}
private void appendButton_Click(object sender, EventArgs e)
{
provinces = Regex.Matches(richTextBox1.Text, #"\d+(.*?){")
.Cast<Match>()
.Select(m => m.Value)
.ToArray();
for (int i = 0; i < provinces.Length; i++)
{
richTextBox1.Text = richTextBox1.Text.Replace(provinces[i], provinces[i] + System.Environment.NewLine + " " + textBox2.Text);
}
}
}
}
Use regex
\d+(.*?){
tested here
Another way to do it would be to insert the text at the end of each block, by searching for two } characters separated by 0 or more whitespace characters. The regex for this would look like:
Regex.Matches(searchString, "}\\s}");
In either case, when inserting the strings we should start from the last match (at the end of the string) and move backwards towards the beginning, because each insert will change the string length and therefore impact the index at which we want to do the insertion.
For example:
/// <summary>
/// Returns a string with newText inserted into parentText
/// </summary>
/// <param name="newText">The new text to insert</param>
/// <param name="parentText">The parent text to insert into</param>
/// <returns>The parent string with the newText inserted</returns>
private string GetInsertedText(string newText, string parentText)
{
var newParentText = parentText;
var matches = Regex.Matches(newParentText, "}\\s}");
// Replace from the last occurrence, since each insert will
// change the length of our string and alter the insert location
for(int index = matches.Count - 1; index >= 0; index--)
{
var match = matches[index];
newParentText = newParentText.Substring(0, match.Index + 1) +
Environment.NewLine + newText +
newParentText.Substring(match.Index + 1);
}
return newParentText;
}
You also might want to create a method that adds 4 spaces to the beginning of each line of the textBox1.Text so that it has a proper indent after it's inserted. For example:
private string GetIndentedText(string originalText, string indentText = " ")
{
return $"{indentText}{originalText}".Replace("\n", $"\n{indentText}").TrimEnd();
}
The usage of this would look something like:
private void button1_Click(object sender, EventArgs e)
{
// Check for any text requirements here (like it should contain
// an open brace, an equals sign, end with a close brace, etc.)
if (textBox1.Text.Length > 0)
{
// Insert the new (indented) text into our RichTextBox
richTextBox1.Text = GetInsertedText(GetIndentedText(textBox1.Text),
richTextBox1.Text);
// Clear the input textbox
textBox1.Text = "";
}
}

Conversion program storing information in array and using a combobox

This is homework (I always try to point that out so it's up front). The program is a conversion program. The user picks a conversion option from a combo box and then enters a length (ie: Feet to meters) when the user hits calculate the program calculates the conversion. I have several questions because the array part is confusing me. I wanted to make sure I am going in the right direction.
I think I am using my array to populate my combo box (I used an example provided although I do not fully understand it). When the user hits the calculate button should I be storing my conversion values in the same array? something like:
string [,] conversions = { {kilometers to miles, .11111}, {miles to kilometers, .11111}}
Or am I heading in the right direction with what I have? To be clear as it is coded the array populates my combobox so if I add the extra data then it will display those numbers in the combobox, which isn't really what I am going for.
My next question, when the user hits calculate button how is it going to know what option the user has selected? I think it has something to do with index but I'm confused as far as what is actually declaring it?
*****Disregard this question. I think I found an answer*********
Answer on Updating Labels
Finally I think my last question is the page has labels next to the textboxes so if the user chooses 'Miles to kilometers" the entry textbox is going to say Miles and then the answer textbox would say Kilometers... What is that called? I need to find it in my book and cannot. I know I'm missing something but I'm trying to find either an example or where in the book it was covered and I'm simply not seeing it.
Below is my code that I currently have.
public partial class FrmConversions : Form
{
const double Miles_To_Kilometers = 1.6093;
const double Kilometers_To_Miles = 0.6214;
const double Feet_To_Meters = 0.3048;
const double Meters_To_Feet = 3.2808;
const double Inches_To_Centimeters = 2.54;
const double Centimeters_To_Inches = 0.3937;
public FrmConversions()
{
InitializeComponent();
}
private void btnExit_Click(object sender, EventArgs e)
{
this.Close();
}
private void FrmConversions_Load(object sender, EventArgs e)
{
cboConversions.Items.Clear(); //clear the combobox
string[,] conversions =
{
{"Kilometers to Miles" , "Miles to Kilometers"},
{"Feet to Meters" , "Meters to Feet"},
{"Inches to Centimeters", "Centimeters to Inches"}
};
foreach (string str in conversions)
{
cboConversions.Items.Add(str);
}
}
private void btnClear_Click(object sender, EventArgs e)
{
txtEntry.Clear();
txtAnswer.Clear();
}
public bool IsDecimal(TextBox txtEntry, string name)
{
try
{
Convert.ToDecimal(txtEntry.Text);
return true;
}
catch (FormatException)
{
MessageBox.Show(name + " must be a decimal value.", "Entry Error");
txtEntry.Focus();
return false;
}
}
private void btnCalculate_Click(object sender, EventArgs e)
{
int index = cboConversions.SelectedIndex;
if (index != -1)
{
try
{
if (IsDecimal())
{
txtAnswer.Text = ToString;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + "\n\n" +
ex.GetType().ToString() + "\n" +
ex.StackTrace, "exception");
}
}
}
}
}
}
There are many ways to do this, a Dictionary would be neat?
In this example, the Keys of the dictionary (the strings I specified) are loaded into the combo box. Later, those strings can be used to retrieve the conversion value from the dictionary.
// Declare at the top
Dictionary<string, double> conversions = {
{ "Kilometers to Miles", Kilometers_To_Miles},
{ "Miles to Kilometers", 1 / Kilometers_To_Miles},
{ "Feet to Meters", Feet_To_Meters},
{ "Meters to Feet", 1 / Feet_To_Meters},
etc
};
// In Form Load
foreach (string str in conversions.Keys)
{
cboConversions.Items.Add(str);
}
// In btnCalculate_Click
var conversionValue = conversions[cboConversions.Text];
var convertedValue = (double)txtEntry.Text * conversionValue; // Need to validate is numeric
txtAnswer.Text = convertedValue
If you were hellbent on using arrays then this would work too, but cheats by using LINQ at the end:
// Declare at the top
object[,] conversions = {
{ "Kilometers to Miles", Kilometers_To_Miles},
{ "Miles to Kilometers", 1 / Kilometers_To_Miles},
{ "Feet to Meters", Feet_To_Meters},
{ "Meters to Feet", 1 / Feet_To_Meters},
etc
};
// In Form Load
foreach (string str in conversions)
{
cboConversions.Items.Add(str[0]);
}
// In btnCalculate_Click
var conversionValue = conversions.First(x => x[0] == cboConventions.Text)[1];
var convertedValue = (double)txtEntry.Text * conversionValue; // Need to validate is numeric
txtAnswer.Text = convertedValue

How to improve search speed in data grid view

I have a datagridview which contain student details (first name, last name, gender, degree and burn date)
I write this code to perform "keyboard search" (for this example I "load" the data locally):
public class StudentDetails
{
public string firstName;
public string lastName;
public string gender;
public string degree;
public DateTime burnDate;
};
public List<StudentDetails> studentSearchList = new List<StudentDetails>(); // Contain all dgv for searches
private void Form1_Load(object sender, EventArgs e)
{
refreshDataGridView();
}
private void refreshDataGridView()
{
for (int i = 0; i < 1000; i++)
{
StudentDetails sd = new StudentDetails();
sd.firstName = GetRandomFirstName();
sd.lastName = GetRandomLastName();
sd.gender = GetRandomGender();
sd.degree = GetRandomDegree();
sd.burnDate = GetRandomBurnDate();
studentSearchList.Add(sd);
addRowToDataGrid(sd);
}
}
bool detailsContain(StudentDetails sd, string s)
{
if (sd.firstName.ToLower().Contains(s) ||
sd.lastName.ToLower().Contains(s) ||
sd.gender.ToLower().Contains(s) ||
sd.degree.ToLower().Contains(s) ||
sd.burnDate.ToShortDateString().ToString().Contains(s))
return true;
else
return false;
}
void addRowToDataGrid(StudentDetails sd)
{
string[] row = new string[] { sd.firstName, sd.lastName, sd.gender, sd.degree, sd.burnDate.ToShortDateString().ToString() };
dataGridView1.Rows.Add(row);
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
List<StudentDetails> list_SD = new List<StudentDetails>();
String s = textBox1.Text;
s = s.ToLower().Trim();
foreach (StudentDetails sd in studentSearchList)
if (detailsContain(sd, s)) list_SD.Add(sd);
// Clear old rows
dataGridView1.Rows.Clear();
dataGridView1.Refresh();
// Adding the new rows
foreach (StudentDetails sd in list_SD)
addRowToDataGrid(sd);
}
My problem is the searching is too slowly and I have no idea to improve the speed.
I tried to declare another list that contain all database and to fill studentSearchList just with the last search result until the user press on delete character but it's not so help and it's cost memory…
Maybe someone have good search algorithm to suggest ?
Thank you
You need to keep your records "StudentDetails" in the array, not in the list.
Thereafter, build additional index-array (unsigned int or short)
for each searchable field, and sort indices in those arrays according values
of appropriate fields.
Thereafter, you will just use binary search for each necessary field, which is log(N).
You should first measure what takes time. Is it the search itself (I doubt) or refreshing the datagrid on every keystroke ?

Categories