Storing ListBox items in separate variables - c#

There could be up to four items in my ListBox control. I want to assign the text displayed to string variables but I am running into problems with the index being out of range as soon as it gets to string Two. I know why this is happening (only one item in the listbox...) but I can't seem to get my head around how to do it.
I could possibly construct some kind of if statement to deal with this but I think there may be a more efficient method of doing it, rather than checking if it's less than 2 items, more than 1, etc.
Simple version of my code:
public void button1_Click(object sender, EventArgs e)
{
if (listBox1.Items.Count < 4) {
listBox1.Items.Add(comboBox1.Text);
} else {
System.Windows.Forms.MessageBox.Show("Too many");
}
string One = listBox1.Items[0].ToString();
string Two = listBox1.Items[1].ToString();
string Three = listBox1.Items[2].ToString();
string Four = listBox1.Items[3].ToString();
}
Note that I cannot use an array for this, as I need to access the variables in another application which does not have the ability to iterate through an array or access its indexes.

you could create a temporary array to handle the copying for you:
if (listBox1.Items.Count < 4) {
listBox1.Items.Add(comboBox1.Text);
} else {
System.Windows.Forms.MessageBox.Show("Too many");
}
string[] ListItemsArray= new string[4];
listBox1.Items.CopyTo(ListItemsArray, 0);
//Then you can leave this here:
string One = ListItemsArray[0] ?? "";
string Two = ListItemsArray[1] ?? "";
string Three = ListItemsArray[2] ?? "";
string Four = ListItemsArray[3] ?? "";
The listBox1.Items.CopyTo() method is explained here.
The ?? operator is used if you don't want any value to be null

If its really just up to 4 items, then manually knock it out?
string One = "";
string Two = "";
string Three = "";
string Four = "";
if (listBox1.Items.Count >= 1)
{
One = listBox1.Items[0];
}
if (listBox1.Items.Count >= 2)
{
Two = listBox1.Items[1];
}
if (listBox1.Items.Count >= 3)
{
Three = listBox1.Items[2];
}
if (listBox1.Items.Count >= 4)
{
Four = listBox1.Items[3];
}
Its not elegant, but the job is done.

You could use a for loop over the listBox.Items so you never try to access indices that are out of range.
You could first create an array of strings like so:
string[] names = new string[] { "", "", "", "" };
Then you could use a for loop over the items of the listbox and set the strings of the array of strings you just created to be equal to whatever is in the listBox[index].ToString() like:
for (int i = 0; i < listBox.Items.Count; i++)
{
names[i] = listBox.Items[i].ToString();
}
Finally, you set your original variables with the :
string one = names[0];
string two = names[1];
string three = names[2];
string four = names[3];
If any of the strings above is an empty string, it means you didn't have any item on that position in the listbox or the item you had in the listbox implements ToString() to return an empty string.
Not sure if I understood your problem, but I'd do something like that.

Related

How can I split a string to store contents in two different arrays in c#?

The string I want to split is an array of strings.
the array contains strings like:
G1,Active
G2,Inactive
G3,Inactive
.
.
G24,Active
Now I want to store the G's in an array, and Active or Inactive in a different array. So far I have tried this which has successfully store all the G's part but I have lost the other part. I used Split fucntion but did not work so I have tried this.
int i = 0;
for(i = 0; i <= grids.Length; i++)
{
string temp = grids[i];
temp = temp.Replace(",", " ");
if (temp.Contains(' '))
{
int index = temp.IndexOf(' ');
grids[i] = temp.Substring(0, index);
}
//System.Console.WriteLine(temp);
}
Please help me how to achieve this goal. I am new to C#.
If I understand the problem correctly - we have an array of strings Eg:
arrayOfStrings[24] =
{
"G1,Active",
"G2,Inactive",
"G3,Active",
...
"G24,Active"
}
Now we want to split each item and store the g part in one array and the status into another.
Working with arrays the solution is to - traverse the arrayOfStrings.
Per each item in the arrayOfStrings we split it by ',' separator.
The Split operation will return another array of two elements the g part and the status - which will be stored respectively into distinct arrays (gArray and statusArray) for later retrieval. Those arrays will have a 1-to-1 relation.
Here is my implementation:
static string[] LoadArray()
{
return new string[]
{
"G1,Active",
"G2,Inactive",
"G3,Active",
"G4,Active",
"G5,Active",
"G6,Inactive",
"G7,Active",
"G8,Active",
"G9,Active",
"G10,Active",
"G11,Inactive",
"G12,Active",
"G13,Active",
"G14,Inactive",
"G15,Active",
"G16,Inactive",
"G17,Active",
"G18,Active",
"G19,Inactive",
"G20,Active",
"G21,Inactive",
"G22,Active",
"G23,Inactive",
"G24,Active"
};
}
static void Main(string[] args)
{
string[] myarrayOfStrings = LoadArray();
string[] gArray = new string[24];
string[] statusArray = new string[24];
int index = 0;
foreach (var item in myarrayOfStrings)
{
var arraySplit = item.Split(',');
gArray[index] = arraySplit[0];
statusArray[index] = arraySplit[1];
index++;
}
for (int i = 0; i < gArray.Length; i++)
{
Console.WriteLine("{0} has status : {1}", gArray[i] , statusArray[i]);
}
Console.ReadLine();
}
seems like you have a list of Gxx,Active my recomendation is first of all you split the string based on the space, which will give you the array previoulsy mentioned doing the next:
string text = "G1,Active G2,Inactive G3,Inactive G24,Active";
string[] splitedGItems = text.Split(" ");
So, now you have an array, and I strongly recommend you to use an object/Tuple/Dictionary depends of what suits you more in the entire scenario. for now i will use Dictionary as it seems to be key-value
Dictionary<string, string> GxListActiveInactive = new Dictionary<string, string>();
foreach(var singleGItems in splitedGItems)
{
string[] definition = singleGItems.Split(",");
GxListActiveInactive.Add(definition[0], definition[1]);
}
What im achiving in this code is create a collection which is key-value, now you have to search the G24 manually doing the next
string G24Value = GxListActiveInactive.FirstOrDefault(a => a.Key == "G24").Value;
just do it :
var splitedArray = YourStringArray.ToDictionary(x=>x.Split(',')[0],x=>x.Split(',')[1]);
var gArray = splitedArray.Keys;
var activeInactiveArray = splitedArray.Values;
I hope it will be useful
You can divide the string using Split; the first part should be the G's, while the second part will be "Active" or "Inactive".
int i;
string[] temp, activity = new string[grids.Length];
for(i = 0; i <= grids.Length; i++)
{
temp = grids[i].Split(',');
grids[i] = temp[0];
activity[i] = temp[1];
}

String Manupilation Remove and Add String

I am trying to remove part of string value from var1 and then pasting it into another var2 and then into var2. While doing so I update the values of the original variables. So if string length in var1 exceeds max length of 10 it then carries out this manipulation.
The code shown below works fine however I am not sure if this is the best approach of removing part of string and assigning it to a var, updating the value in original variable etc
if (var1.Length > 10)
{
var newVar2 = var1.Remove(0, 10); // Grab the string from var1 and assign
var1 = var1.Remove(10); // Update value and remove the part of string
var2 = newVar2; // Save the newly removed string into var2
if (var2.Length > 10)
{
var newVar3 = var2.Remove(0, 10);
var2 = var2.Remove(10);
var3 = newVar3;
}
}
Is there a better approach?
There are several approaches for string manipulation, but for your case just slimming down your code a bit to remove unneccesary assignments and instantiation should be fine:
if (var1.Length > 10) {
var2 = var1.Remove(0, 10);
var1 = var1.Remove(10);
if (var2.Length > 10) {
var3 = var2.Remove(0, 10);
var2 = var2.Remove(10);
}
}
Another option is to store the string in a List<string> via a loop; this way you won't need a new var for every occasion that the length exceeds 10:
private List<string> SlimStrings(string var1) {
List<string> vars = new List<string>();
string val = string.Empty;
for (int i = 0; i < var1.Length; i++) {
if (i % 10 == 0) {
vars.Add(val);
val = string.Empty;
}
val += var1[i];
}
return vars;
}
In this situation the final string in vars should be less than or equal to 10 in length. Everything prior should be equal to 10 in length. You then access each var via it's index (remembering that C# is a zero based language):
List<string> vars = SlimStrings("askljdngakjdsfngiewurnkajsdnicoebrlpvknas");
var var1 = vars[0];
var var2 = vars[1];
var var3 = vars[2];
Now granted, you'll either have to know the Count of vars in the list prior, or come up with a system for accessing such as a loop like the one that created it (or a foreach loop for simplicity) following the same principal:
private void UseVars(List<string> vars) {
foreach (string s in vars)
DoSomethingWith(s);
// OR
for (int i = 0; i < vars.Count; i++)
DoSomethingWith(vars[i]);
}
Spaces count when working with strings. Unless you truly want spaces in your new values, you should use trim() to remove leading and trailing spaces.
Hard to know what your requirements are given your question. Strings are immutable so you're creating new strings when you do string the string manipulation that you've shown. In general you'd like to create as few as possible. If you're requirements are to create multiple strings from a single string you have no choice, if you're building a single string use StringBuilder. If you're simply truncating the string then just do it in one shot:
var input = "abcdefghijklmnopqrstuvwxyz";
Console.WriteLine($"{input.Length}: {input}");
var truncated = input.Remove(0, input.Length - 10);
Console.WriteLine($"{truncated.Length}: {truncated}");

Dynamically create variables from splitting string c#

I am making a web service for an app with Tesseract Ocr 3.02.
I want to create variables on depending of how many informations I get on the business card and after that classify information from a string.
For example:
Tel. +496123456789$Mobil +49123456789$kai.kalsbach#gmail.com$www.google.com$Kai Kalsbach$Muster Str 1a$40599 Düsseldorf$"
And then like this:
-Telephone number
-First Name
-Last Name
-Email
-Address
That was my first idea:
string endText1 = text.Split('$')[0];
string endText2 = text.Split('$')[1];
string endText3 = text.Split('$')[2];
string endText4 = text.Split('$')[3];
string endText5 = text.Split('$')[4];
string endText6 = text.Split('$')[5];
string endText7 = text.Split('$')[6];
string endText8 = text.Split('$')[7];
and after that i would classify the variables.
but in many cases I get the following exception because the number of informations can vary depending of business card.
System.IndexOutOfRangeException: Index was outside the bounds of the array c#
The IndexOutOfRangeException exception is thrown because the code tries to access an item outside the array length.
My proposition : I created formattedArray with contains always 8 items and I copied the splited array to this formattedArray. With that, you have no more IndexOutOfRangeException because the item missing in text.Split('$') is null in formattedArray
var a = text.Split('$');
var formattedArray = new string[8];
Array.Copy(a, formattedArray, a.Length);
string endText1 = formattedArray [0];
string endText2 = formattedArray [1];
string endText3 = formattedArray [2];
string endText4 = formattedArray [3];
string endText5 = formattedArray [4];
string endText6 = formattedArray [5];
string endText7 = formattedArray [6];
string endText8 = formattedArray [7];
string[] Splitted = text.Split('$');
And you mentioned you want to make a decision based on the number of elements the split spits out
int Count = Splitted.Length;
switch(Count)
{ case 0: //DoStuff
break;
....
default:
break;
}
In your case, it is better to use the following:
string[] stringList = text.Split('$');
foreach(string val in stringList)
{
//your logic.
}
You can split the string once using the .Split method.
Then afterwards run it in a foreach or for loop. I believe your logic is based on the amount of strings, so you are looking for a 'for' loop.
string[] split = text.Split('$');
for (int i = 0; i < split.Length; i++)
{
var text = split[i];
// Your logic here...
switch (i) // for logic based on the index of the string
{
case 0:
// do something
break;
case 1:
// do something
break;
}
}
The IndexOutOfRangeException exception is thrown because the code tries to access the 8th item in a 7-item array :
string endText8 = text.Split('$')[7];
Indexes in .NET collections are 0-based which means 7 refers to the 8th element.
By default, String.Split will return empty fields as well. This means that either the string isn't the same as the one posted here, or that the StringSplitOptions.RemoveEmptyEntries was used
String.Split returns a string array that can be stored in a string[] variable. There's no need to repeat String.Split, or use multiple variables :
var items = text.Split(new[]{'$'},StringSplitOptions.RemoveEmptyEntries);
Creating a class from this array is simple enough that you probably don't need to create a custom parser :
class Record
{
public string Telephone {get;set;}
...
}
var items = text.Split('$');
var record=new Record
{
Telephone=items[0],
Mobile=items[1],
...
};
Another easy way to do that is to use a try, then all variables will be created until the index has reached its maximum.
string[] strArray = text.Split('$');
Try {
string endText1 = strArray[0];
string endText2 = strArray[1];
string endText3 = strArray[2];
string endText4 = strArray[3];
string endText5 = strArray[4];
string endText6 = strArray[5];
string endText7 = strArray[6];
string endText8 = strArray[7];
}
catch
{
//nothing
}
Create factory and recognizers
public class PhoneItem : IItem
{
public PhoneItem(string text)
{
// some code
}
}
public interface IRecognizer
{
IItem Recognize(int index, string text);
}
public class PhoneRecognizer : IRecognizer
{
public IItem Recognize(int index, string text)
{
return index == 0 ? new PhoneItem(text) : null;
}
}
public class ItemFactory
{
private IEnumerable<IRecognizer> _recognizers = new []
{
new PhoneRecognizer(),
new FullNameRecognizer()
};
public IItem CreateItem(int index, string text)
{
foreach (var rec in _recognizers)
{
var item = rec.Recognize(index, text);
if (item != null)
{
return item;
}
}
throw new Exception("Item not recognized");
}
}
Split string to pieces
var parts = text.Split('$');
Use the factory to create objects
var factory = new ItemFactory();
var items = new List<IItem>();
for (int i = 0; i < parts.Length; i++)
{
items.Add(factory.CreateItem(i, parts[i]));
}
// do whatever you wants

Pass string value created in one function as parameter to function

I have a function called ValidColumns that, when finished will contain a string of id values joined by the pipe character "|."
private bool ValidColumns(string[] curGlobalAttr, int LineCount)
{
//test to see if there is more than 1 empty sku mod field in the imported file
string SkuMod = GetValue(curGlobalAttr, (int)GlobalAttrCols.SKU);
if(SkuMod =="")
ids += string.Join("|", OptionId);
}
What I want to do is take the ids string and pass it as a reference into another function to check to see if it contains duplicate values:
protected bool CheckForDuplicates(ref string ids)
{
bool NoDupes = true;
string[] idSet = ids.Split('|');
for (int i = 1; i <= idSet.Length - 1; i++)
{
if (idSet[i].ToString() == idSet[i - 1].ToString()) { NoDupes = false; }
}
return NoDupes;
}
But I am not sure how to do it properly? It seems so easy but I feel like I'm making this out to be much harder than it needs to be.
if (idSet[i].ToString() == idSet[i - 1].ToString())
You're only checking each value against the previous value. That would work if the values were sorted, but an easier method would just be to get a distinct list and check the lengths:
return (idSet.Length == idSet.Distinct().Count());
The second part of D Stanley's answer is what you want
public bool CheckForDuplicates(string value)
{
string[] split = value.Split('|');
return split.Length != split.Distinct().ToArray().Length;
}
You need a nested loop to do this which will look at each item and compare it to another item. This also will eliminate checking it against itself so it does not always return false.
In this we will track what we have already checked and only compare the new items against items after that slowly shrinking the second loop down in size to eliminate duplicate checks.
bool noDupes = true;
int currentItem = 0;
int counter = 0;
string[] idSet = ids.Split('|');
while(currentItem < idSet.Count)
{
counter = currentItem + 1;
while(counter < idSet.Count)
{
if(idSet[currentItem].ToUpper() == idSet[counter].ToUpper())
{
noDupes = false;
return noDupes;
}
counter ++;
}
currentItem ++;
}
return noDupes;
Edit:
It was pointed out an option I posted as an answer would always return false so I removed that option and adjusted this option to be more robust and easier to step through logically.
Hope this helps :)

how to store a part of dropdownlist text in a dynamically generated property

here is my code:
EntityLayer.Entity[] en = new EntityLayer.Entity[counter];
int count = 0;
for (int i = 0; i < CheckBoxList1.Items.Count; i++)
{
if (CheckBoxList1.Items[i].Selected == true)
{
en[count] = new EntityLayer.Entity();
en[count].all_Emp_Mobile = DropDownList1.SelectedValue.ToString();
en[count].all_Emp_Name = DropDownList1.Text;
en[count].all_Stu_Mobile = CheckBoxList1.Items[i].Value.ToString();
count++;
}
}
now the thing is that the dropdown list text has both the name and mobile number concatenated and seperated by "/" character. what i want to do is to just save the name of the person in the property en[count].all_Emp_Name., is there a method in c# like Remove or something like that which can remove the the latter part i.e the mobile number from the string.
Remove method demands the index from where you want to remove the text and for that i might use
Indexof but i am a little confused here how to go about it, as the property is generated dynamically in the for loop
do something like this:
string DropDownText = "EhsanSajjad/03123009099";
string[] temp = DropDownText.Split('/');
string personName = temp[0];
string CellNumber = temp[1];
got it finally....
int index = DropDownList1.SelectedItem.Text.LastIndexOf('/');
string empName = DropDownList1.SelectedItem.Text.Remove(index);
en[count].all_Emp_Name = empName;
this seems to be working just perfect.

Categories