searching an arraylist - c#

I have a arraylist in my web application project in asp.net/C#/VS2008 and I'm using .net 3.5
I'm adding contents to the arraylist using a class which is defined as follows:
using System.Web;
class ShoppingCartDataStore
{
private string componentName;
private string componentPrice;
private string componentFileSize;
private string componentDescription;
public ShoppingCartDataStore(string componentName, string componentPrice, string componentFileSize, string componentDescription){
this.componentName = componentName;
this.componentPrice = componentPrice;
this.componentFileSize = componentFileSize;
this.componentDescription = componentDescription;
}
public string ComponentName
{
get
{
return this.componentName;
}
}
public string ComponentPrice
{
get
{
return this.componentPrice;
}
}
public string ComponentFileSize
{
get
{
return this.componentFileSize;
}
}
public string ComponentDescription
{
get
{
return this.componentDescription;
}
}
}
and I'm adding contents to the arraylist by following code:
ArrayList selectedRowItems = new ArrayList();
selectedRowItems.Add(new ShoppingCartDataStore(componentName, componentPrice, fileSize, componentDescription));
Suppose I want to search this arraylist after adding few values in this manner with componentName as the key. I tried the following code but I'm just not able to find a way to do this:
ArrayList temporarySelectedItemsList = new ArrayList();
ArrayList presentValue = new ArrayList();
string key = componentName; //some specific component name
temporarySelectedItemsList = selectedRowItems;
for (int i = 0; i < temporarySelectedItemsList.Count; i++)
{
presentValue = (ArrayList)temporarySelectedItemsList[i];
}

var results = selectedRowItems.OfType<ShoppingCartDataStore>().Where(x=>x.ComponentName == "foo")
of course you could get rid of the OfType if you were using a generic list rather than a arraylist
EDIT: So, I have no idea why you would NOT use LINQ or generics if you are in 3.5. But if you must:
ArrayList results = new ArrayList();
foreach (ShoppingCartDataStore store in selectedRowItems)
{
if(store.ComponentName == "foo"){
results.Add(store);
}
}

I'm sick and this is untested, but I think it'll work. :)
List<ShoppingCartDataStore> aList = new List<ShoppingCartDataStore>();
// add your data here
string key = componentName; //some specific component name
// Now search
foreach (ShoppingCartDataStore i in aList)
{
if (i.ComponentName == key)
{
// Found, do something
}
}

Related

Checking list for custom object

If you have made a list of Custom objects is it a must to have to do with Hashcodes if you wanna check that list to see if it contains a object before adding it, I mean so that you do not get duplicates in the list or is there an easier way basically I want to use the contains method on a custom object list to see if the object I want to add already exists in the list and if there then is an easier way then to have to deal with hashcodes?
This is my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DataConverter.Objects;
namespace DataConverter.Converters
{
class CategoryConverter
{
private Category category;
private SubCategory subCategory;
private ExcellObj excellObj;
public CategoryConverter(string path)
{
excellObj = new ExcellObj(path);
}
public List<Category> getCategoryListExcel()
{
List<Category> categories = new List<Category>();
List<string> ColumnNames = new List<string> { "Group1", "Group1Descr" };
List<int> CorrectColumn = new List<int>();
for(int i = 0; i < ColumnNames.Count; i++)
{
CorrectColumn.Add(excellObj.findColumn(ColumnNames[i]));
}
for(int i = 2; i < excellObj.allRows; i++)
{
categories.Add(category = new Category(excellObj.getValuesFromCell(i, CorrectColumn[1]), excellObj.getValuesFromCell(i, CorrectColumn[0]), "Home"));
}
return categories;
}
public List<List<SubCategory>> getSubCategory()
{
List<SubCategory> subCategories1 = new List<SubCategory>();
List<SubCategory> subCategories2 = new List<SubCategory>();
List<List<SubCategory>> subCategoriesList = new List<List<SubCategory>>();
List<string> ColumnNamesSubCategory1 = new List<string> { "Group2", "Group2Descr" };
List<string> ColumnNamesSubCategory2 = new List<string> { "Group3", "Group3Desc" };
List<int> CorrectColumn1 = new List<int>();
List<int> CorrectColumn2 = new List<int>();
for(int i = 0; i < ColumnNamesSubCategory1.Count; i++)
{
CorrectColumn1.Add(excellObj.findColumn(ColumnNamesSubCategory1[i]));
CorrectColumn2.Add(excellObj.findColumn(ColumnNamesSubCategory2[i]));
}
for(int i = 1; i < excellObj.allRows; i++)
{
subCategories1.Add(subCategory = new SubCategory(excellObj.getValuesFromCell(i, CorrectColumn1[1]),excellObj.getValuesFromCell(i,CorrectColumn1[0]), "Home"));
subCategories2.Add(subCategory = new SubCategory(excellObj.getValuesFromCell(i,CorrectColumn2[1]), excellObj.getValuesFromCell(i,CorrectColumn2[0]), "Home"));
}
subCategoriesList.Add(subCategories1);
subCategoriesList.Add(subCategories2);
return subCategoriesList;
}
public void finnishedUsingExcel()
{
excellObj.CloseApplication();
}
}
}
and what i whant to happen is that i whant to run a
if(categories.Contains(category) == false){
categories.add(category)
}
i do not understand this part in the documentation?
public Person(string lastName, string ssn)
{
if (Regex.IsMatch(ssn, #"\d{9}"))
uniqueSsn = $"{ssn.Substring(0, 3)}-{ssn.Substring(3, 2)}-{ssn.Substring(5, 4)}";
else if (Regex.IsMatch(ssn, #"\d{3}-\d{2}-\d{4}"))
uniqueSsn = ssn;
else
throw new FormatException("The social security number has an invalid format.");
this.LastName = lastName;
}
Assuming you have a code like this:
List<CustomObject> listOfCustomObjects = new List<CustomObject>();
Solution 1
If so, you can use listOfCustomObjects.Contains(customObject) to find out if customObject is in listOfCustomObjects. You should add using System.Linq; to the top of your code in order to use this method.
Solution 2
Another way to not have duplicates in your list is basically not using a List. You can use HashSet instead. With this method, duplicate objects won't be added to your list automatically. HashSet is also in LINQ Library, so you should add the line using System.Linq; for this solution too. Here's an example how to create a new HashSet with your CustomObject class:
HashSet<CustomObject> setOfCustomObjects = new HashSet<CustomObject>();
You really should have your class implement IEquatable if it's reasonable to do so and you're going to check for equality with any frequency, just so it does not bite you. The "Contains" method will work, but only to test that the exact same instance is present, not necessarily one that just shares matching properties. Consider the following code:
class Program
{
static void Main(string[] args)
{
var classInstance = new MySampleClass("testA", "testB");
var classList = new List<MySampleClass>();
classList.Add(classInstance);
if (classList.Contains(new MySampleClass("testA", "testB")))
{
Console.WriteLine("true");
}
else
{
Console.WriteLine("false");
}
if (classList.Contains(classInstance))
{
Console.WriteLine("true");
}
else
{
Console.WriteLine("false");
}
}
}
public class MySampleClass
{
public string SampleProperty1 { get; set; }
public string SampleProperty2 { get; set; }
public MySampleClass(string sampleProperty1, string sampleProperty2)
{
SampleProperty1 = sampleProperty1;
SampleProperty2 = sampleProperty2;
}
}
Even though we're checking for the presence of the class that has the exact same values as the one we previously added, they're still separate instances and you'll end up with duplicates in your list.
An alternative in the very limited case would be to use a LINQ method to check whether the list already contains an entry with a property that can be compared, such as an int ID or something:
yourList.Any(item => item.Id.Equals(otherItem.Id));
Again, if it's more than a one off, implement it the right way with IEquatable. See Microsoft's documentation

C# custom add in a List

I have the following list of strings :
var files = new List<string> {"file0","file1","file2","file3" };
I would like to be able to add new files to this list, but if the inserted file is present in the list, I would like to insert custom value that will respect the following format $"{StringToBeInserted}"("{SomeCounter}
For instance : try to add "file0" and "file0" is already I would like to insert "file0(1)". If I try again to add "file0" ... I would like to insert with "file0(2)" and so on ... Also, I would like to provide a consistency, for instance if I delete "file0(1)" ... and try to add again "item0" ... I expect that "item0(1)" to be added. Can someone help me with a generic algorithm ?
I would use a HashSet<string> in this case:
var files = new HashSet<string> { "file0", "file1", "file2", "file3" };
string originalFile = "file0";
string file = originalFile;
int counter = 0;
while (!files.Add(file))
{
file = $"{originalFile}({++counter})";
}
If you have to use a list and the result should also be one, you can still use my set approach. Just initialize it with your list and the result list you'll get with files.ToList().
Well, you should create your own custom class for it, using the data structure you described and a simple class that includes a counter and an output method.
void Main()
{
var items = new ItemCountList();
items.AddItem("item0");
items.AddItem("item1");
items.AddItem("item2");
items.AddItem("item0");
items.ShowItems();
}
public class ItemCountList {
private List<SimpleItem> itemList;
public ItemCountList() {
itemList = new List<SimpleItem>();
}
public void DeleteItem(string value) {
var item = itemList.FirstOrDefault(b => b.Value == value);
if (item != null) {
item.Count--;
if (item.Count == 0)
itemList.Remove(item);
}
}
public void AddItem(string value) {
var item = itemList.FirstOrDefault(b => b.Value == value);
if (item != null)
item.Count++;
else
itemList.Add(new SimpleItem {
Value = value,
Count = 1
});
}
public void ShowItems() {
foreach (var a in itemList) {
Console.WriteLine(a.Value + "(" + a.Count + ")");
}
}
}
public class SimpleItem {
public int Count {get; set;}
public string Value {get; set;}
}

Add objects to arraylist and read them

I'm trying to add objects of DataPerLabel to my Arraylist allData, following the code of DataPerLabel:
class DataPerLabel
{
public String labelName;
public String labelAdress;
public String dataType;
public DataPerLabel(String labelName, String labelAdress, String dataType)
{
this.labelName = labelName;
this.labelAdress = labelAdress;
this.dataType = dataType;
}
public String getLabelName()
{
return labelName;
}
public String getLabelAdress()
{
return labelAdress;
}
public String getDataType()
{
return dataType;
}
}
In the following code I try to add the objects of DataPerLabel to my arraylist:
submitButton.Click += (sender, args) =>
{
String label = textboxLabel.Text;
String adress = textboxAdress.Text;
String dataType = "hey";
if (buttonsLabelBool.Checked)
{
dataType = "Bool";
}
else if (buttonsLabelReal.Checked)
{
dataType = "Real";
}
else if (buttonsLabelInt.Checked)
{
dataType = "Int";
}
allData.Add(new DataPerLabel(label, adress, dataType));
};
And finally I try to read out the arrayList by displaying it in a textbox, see the following code:
private void test()
{
Button btn = new Button();
btn.Location = new Point(500,500);
btn.Text = "test";
btn.Click += (sender, args) =>
{
foreach (var item in allData)
{
//Display arraylist per object here
//Something like : item.getLabelName();
}
};
}
I'm not sure what I'm doing wrong, hope you can help!
ArrayList stores a list of System.Object. You need to cast the object back to DataPerLabel as follows:
foreach (var item in allData)
{
((DataPerLabel)item).getLabelName();
}
Alternatively, you could specify the data type in the foreach instead of var as Jakub DÄ…bek pointed out in the comment as follows:
foreach (DataPerLabel item in allData)
{
item.getLabelName();
}
A better approach would be to use generic list/collection List<DataPerLabel> to store the data so that the casting can be avoided.
Yiu should use a List<T> instead of ArrayList. This way every item in your list has the right type already and you can access the members:
foreach (DataPerLabel item in allData)
{
item.GetLabelItem();
}
This assumes allData is defined like this:
allData = new List<DataPerLabel>();
instead of allData = new ArrayList()
If you really have to use an ArrayList than you should cast your item to the actual type. The code above actually does this allready. However you could also use this:
foreach (var item in allData)
{
((DataPerLabel)item).GetLabelItem();
}

Using reflection in ToString method [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I'm trying to clean up my class using reflection.
private List<String> centers = new List<String>();
private List<String> leftWingers = new List<String>();
private List<String> rightWingers = new List<String>();
private List<String> defencemen = new List<String>();
private List<String> goalies = new List<String>();
private List<String> bench = new List<String>();
public List<String> Centers { get { return centers; } set { centers = value; } }
public List<String> LeftWingers { get { return leftWingers; } set { leftWingers = value; } }
public List<String> RightWingers { get { return rightWingers; } set { rightWingers = value; } }
public List<String> Defencemen { get { return defencemen; } set { defencemen = value; } }
public List<String> Goalies { get { return goalies; } set { goalies = value; } }
public List<String> Bench { get { return bench; } set { bench = value; } }
public String ToString()
{
String output = "";
System.Reflection.PropertyInfo[] properties = this.GetType().GetProperties();
foreach (System.Reflection.PropertyInfo property in properties)
{
int count = 0;
foreach (String value in property)
{
count++;
output += "C" + count + ": " + value + System.Environment.NewLine;
}
}
}
This will not work. I cant seem to be able to loop over items of each property because they are collections. Is there a way to get the contents of the String Lists from the PropertyInfo object?
They are not properties, they are fields,so you need to use GetFields
You need to tell GetFields method that you want to get private
members using BindingFlags, otherwise it will look for public and instance members by default.
var fields = this.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
Well, if you really want properties, the first thing is that you do not have properties on your code. You have just some attributes. Change it for properties if it is the case, for sample:
private List<String> centers { get; set; }
private List<String> leftWingers { get; set; }
private List<String> rightWingers { get; set; }
private List<String> defencemen { get; set; }
private List<String> goalies { get; set; }
private List<String> bench { get; set; }
Then you could read them as collections and read values, for sample:
public String ToString()
{
StringBuilder output = new StringBuilder();
System.Reflection.PropertyInfo[] properties = this.GetType().GetProperties();
foreach (System.Reflection.PropertyInfo property in properties)
{
var values = property.GetValue(this, null) as IEnumerable<String>;
if (values != null)
{
int count = 0;
foreach (String value in values)
{
count++;
output.AppendLine(string.Format("C{0}: {1}", count, value));
}
}
}
return output.ToString();
}
Another case is to read the fields and avoid converting it to properties. Look the Selman22's answer!
Your problem can be drastically simplified using Enumerable.Concat, Enumerable.Select and string.Join:
IEnumerable<string> allItems = centers.Concat(leftWingers)
.Concat(rightWingers)
.Concat(defencemen)
.Concat(goalies)
.Concat(bench);
return string.Join
(
Environment.NewLine,
allItems.Select((item, index) => $"C {index + 1}: {item}")
);
These are fields, so you need to use GetFields to obtain them. Please note also that fields returned by reflection are just metadata, they don't contain the data that you need.
To get the data, you need to use the GetValue method to get the field value for the current object.
Then, to be able to enumerate the collection in the field, you need to cast it as IEnumerable<string>.
Here is how it would look like:
public String ToString()
{
String output = "";
var fields = this.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
foreach (var field in fields)
{
int count = 0;
foreach (String value in (IEnumerable<string>) field.GetValue(this))
{
count++;
output += "C" + count + ": " + value + System.Environment.NewLine;
}
}
return output;
}
Since you have only 6 collections, you can have a solution that does not involve reflection. Here is an example:
public String ToString()
{
String output = "";
var collections = new[] {centers, leftWingers, rightWingers, defencemen, goalies, bench};
foreach (var field in collections)
{
int count = 0;
foreach (String value in field)
{
count++;
output += "C" + count + ": " + value + System.Environment.NewLine;
}
}
return output;
}
Please consider using a StringBuilder instead of a string. Using a string to concatenate strings will hurt performance.

how to get each item without using a loop from string array in c#

Iam using 3 string arrays.i want to get each item corresponds to the index,ie if itnme will have the second item,then i need to get second item from other two string arrays such as qntity,price.How can i possible this?
string[] itmnme= new string[0] { };
string[] price= new string[0] { };
string[] qntity= new string[0] { };
foreach (string iname in itmnme)
{
foreach (string qnt in qntity)
{
foreach (string prc in price)
{
}
}
}
I think the best way that you can adopt is, using List Of Classes:
public class Product
{
public string itmnme;
public string price;
public string qntity;
}
Your List will be like :
List<Product> productList = new List<Product>{new Product()
{itmnme="item1",price="20",qntity="1"},
new Product(){itmnme="item2",price="220",qntity="3"} };
So that you can Iterate the List and easily get value from the List:
foreach (var item in productList)
{
string itmnme=item.itmnme;
string price = item.price;
string qntity=item.qntity;
}
Assuming the size of all your arrays is identical you can use such code:
for(int i=0; i<itmnme.Length; i++)
{
var name = itmnme[i];
var quantity = qntity[i];
var price = price[i];
// do what you need with these values
}
Sounds like you will need to retrieve data from each array, given a position, is that right? If so you can have a method like:
public string[] getItemAtPosition(int position)
{
string[] dataResult = new string[0]{};
string itmnmeItem = itmnme[position];
string qntityItem = qntity[position];
string priceItem = price[position];
dataResult.add(itmnmeItem);
dataResult.add(qntityItem);
dataResult.add(priceItem);
return dataResult;
//now this array contains data from each array at the specified position
}

Categories