I'm building an android application where I need to create a simple list of String items, which i will then add a specific control for each item in the list.
This is the list I want to create:
List<String> projects = new List<String>(); // How?
The code I was trying:
String projects = new string[] { "hey","yo","app","xamarin","c","xaml" };
I need to count the items, something like this:
int amount = projects.Count(); // Can I do this?
Then adding the controls for each item in the list
// Add the tiles, one by one
for (int i = 0; i < amount; i++)
{
// Inflate the tile
var tile = LayoutInflater.Inflate (Resource.Layout.Tile, null);
// Set its attributes
tile.FindViewById<TextView> (Resource.Id.projectName).Text = currentProject;
// Add the tile
projectScrollView.AddView (tile);
}
"currentProject" string is retrieved from SharedPreferences, just haven't got that far yet
var projects = new List<String>() { "hey","yo","app","xamarin","c","xaml" };
if you are using the array to store what values you want in your list use the foreach
List<string>project = new List<string>();
string[] projects = { "hey","yo","app","xamarin","c","xaml" };
foreach(string str in projects)
{
project.Add(str);
}
for (int i = 0; i < projects.Length; i++)
{
// Inflate the tile
var tile = LayoutInflater.Inflate (Resource.Layout.Tile, null);
// Set its attributes
tile.FindViewById<TextView> (Resource.Id.projectName).Text = currentProject;
// Add the tile
projectScrollView.AddView (tile);
}
// you can get items from your list by using project.Count, your List<string> instead of projects.Length your array and take information from your list and output your tiles that way
To initialize a List<string> with collection initializer use the below syntax.
List<String> projects = new List<String>(){"hey","yo","app","xamarin","c","xaml"};
Count is not a method it is a property. You need property syntax.
int amount = projects.Count;
int amount = projects.Length;
that is how you can set the value of the int. It doesnt appear that you are populating your list with that code.
Related
I hold an array in the following structure
List[] pageStore = new List[2];
Each cell of the array will contain a list of Page objects.
I wrote a function that ran in a loop and in each iteration creates a new list of Page.
I keep the list created in the above List.
Before each iteration I delete the contents of pages and the deletion is also done on the array itself.
How can this be prevented so that the array will keep the records I saved?
my code :
List<Page>[] pageStore = new List<Page>[2];
public void LoadExcel(Dictionary<string,string[]> FilePaths){
List<Page> pages = new List<Page>();
int pageStoreIndex = 0;
foreach (KeyValuePair<string, string[]> entry in
FilePaths) {
pages.Clear();
for (int i = 0; i < entry.Value.Length; i++) {
if (i == 0)
pages = fileManager.ParseExcelToObjects(excelDataSet,
ProjectTypeSelected.Name,entry.Key.Equals(Enum.Enums.ConnectorSide.COMBINED.ToString()) ? false : true);
...
...
}
if (pages.Count > 0)
pageStore[pageStoreIndex++] = pages;
}
}
page.Clear() cleared pageStore also.
You need to create a copy of the list.
pageStore[pageStoreIndex++] = new List<Page>(pages);
Like most .Net objects, List<T> is a reference type. Your line:
pageStore[pageStoreIndex++] = pages;
is just storing a reference to the single pages instance. It's not copying the values across. Every array entry is pointing at the same list.
As other answers have said, you need to create a new list each time if you want to keep separate lists:
List<Page>[] pageStore = new List<Page>[2];
public void LoadExcel(Dictionary<string,string[]> FilePaths)
{
int pageStoreIndex = 0;
foreach (KeyValuePair<string, string[]> entry in FilePaths)
{
//create a new list for each loop iteration
var pages = new List<Page>();
for (int i = 0; i < entry.Value.Length; i++)
{
//ps the following lines don't make sense. You've created a new List above,
//but ParseExcelToObjects() ignores it and returns its own list.
//So either your new List<Page>() is pointless, or this call is different in the real code.
if (i == 0)
pages = fileManager.ParseExcelToObjects(excelDataSet, ProjectTypeSelected.Name,entry.Key.EqualsEnum.Enums.ConnectorSide.COMBINED.ToString()) ? false : true);
...
...
}
if (pages.Count > 0)
pageStore[pageStoreIndex++] = pages;
}
}
You've assigned the value in pageStore to be the pages object. You'll need to create a new object using List<T>'s copy constructor:
if (pages.Count > 0)
pageStore[pageStoreIndex++] = new List<Page>(pages);
Variable.cs
public string[] CcEmails { get; set; }
Mail.cs
EDTO.CcEmails = dr["rsh_ccmail"].ToString().Split(';');
here i got two strings eg. xxxx#gmail.com ; yyy#gmail.com
MailProcess.cs
dataRPT1=get data from sql
EDTO.CcEmails = new string[dataRPT1.Rows.Count];
for (int i = 0; i < dataRPT1.Rows.Count; i++)
{
EDTO.CcEmails[i] = dataRPT1.Rows[i]["email_addr"].ToString();
}
Here i got list of string eg.aaa#gmail.com ......
I am try to add with existing but it add only new values..Anyone could help me..
I tend to use union, although that will remove duplicate entries. But to keep all entries you can use Concat on the array.
var emailString = "me#test.com;you#test.com";
string[] emails = emailString.Split(';');
string[] emailsFromSQL = new string[3];
emailsFromSQL[0] = "everyone#test.com";
emailsFromSQL[1] = "everyone2#test.com";
emailsFromSQL[2] = "everyone2#test.com";
//No Duplicates
var combined = emails.Union(emailsFromSQL).ToArray();
//Duplicates
var allCombined = emails.Concat(emailsFromSQL).ToArray();
Thanks
I find the easiest way of doing this is to create a list, add items to the list, then use string.Join to create the new string.
var items = new List<string>();
for (int i = 0; i < dataRPT1.Rows.Count; i++)
{
items.Add(dataRPT1.Rows[i]["email_addr"].ToString());
}
EDTO.CcEmails = string.Join(";", items);
Update after changed question:
If the type of the CcEmails is an array, the last line could be:
EDTO.CcEmails = items.ToArray();
Since having a list<list<>> is bad practice, i have created a class containing 2 lists:
public class TouchSet
{
public List<DateTime> timeList = new List<DateTime>(ammountOfXValues);
public List<int> touchList = new List<int>(ammountOfXValues);
}
Then i have a function that is used to initialize the entire thing so i can use it further down the road:
public void initializeTouchDataListObject()
{
touchSetList = new List<DataStructure.TouchSet>(DataStructure.maxButtonsActive);
List<int> tempTouchList = new List<int>();
List<DateTime> tempTimeList = new List<DateTime>();
for (int a = 0; a < DataStructure.maxButtonsActive; a++)
{
DataStructure.TouchSet tempTouchSet = new DataStructure.TouchSet();
tempTouchSet.timeList = tempTimeList;
tempTouchSet.touchList = tempTouchList;
touchSetList.Add(tempTouchSet);
}
}
This is the loop where i add values to the list:
for (int i = 0; i < DataStructure.maxButtonsActive; i++)
{
if(touchSetList[i].timeList.Count == DataStructure.ammountOfXValues)
{
//RemoveAt removes at the given index within a list
touchSetList[i].timeList.RemoveAt(0);
touchSetList[i].touchList.RemoveAt(0);
//add
touchSetList[i].timeList.Add(DateTime.Now);
touchSetList[i].touchList.Add(temp);
}
else if(touchSetList[i].timeList.Count < DataStructure.ammountOfXValues)
{
//add
touchSetList[i].timeList.Add(DateTime.Now);
touchSetList[i].touchList.Add(temp);
}
else
{
int overLength = touchSetList[i].timeList.Count - DataStructure.ammountOfXValues;
//remove
touchSetList[i].timeList.RemoveRange(0, overLength + 1);
touchSetList[i].touchList.RemoveRange(0, overLength + 1);
//add
touchSetList[i].timeList.Add(DateTime.Now);
touchSetList[i].touchList.Add(temp);
}
}
The issue I'm facing is, that within a single pass through the for loop , it adds temp to every touchList not just the touchList of touchSetList[i].
For example after adding temp to touchSetList[i].touchList every other touchList also contains temp, not just the one where the index i applies to the class within the list.
I'm not sure why the List is behaving this way, and why it adds the value to every list not just the one with the corresponding index. I was under the impression that you can use an index to access a single item within a list. Any pointers or advice is appreciated.
public void initializeTouchDataListObject()
{
touchSetList = new List<DataStructure.TouchSet>(DataStructure.maxButtonsActive);
for (int a = 0; a < DataStructure.maxButtonsActive; a++)
{
List<DateTime> tempTimeList = new List<DateTime>();
List<int> tempTouchList = new List<int>();
DataStructure.TouchSet tempTouchSet = new DataStructure.TouchSet();
tempTouchSet.timeList = tempTimeList;
tempTouchSet.touchList = tempTouchList;
touchSetList.Add(tempTouchSet);
}
}
You don't create a new tempTimeList and tempTouchList for every new tempTouchSet, so they all get passed pointers to THE SAME list.
Do the initialization for tempTimeList and tempTouchList within your loop and you get a new one for every tempTouchSet.
Actually I'd redesign the entire thing. What I read from your code is that you want to store the timestamp of a touch event together with some information about the touch event.
So I'd design a class that contains all that data:
public class TouchInfo
{
public DateTime touchTime;
public int touchEvent;
}
Then you can easily store one list of touch events, instead having to keep two lists in sync.
List<TouchInfo> touchEvents = new List<TouchInfo>();
public void initializeTouchDataListObject()
{
for (int a = 0; a < DataStructure.maxButtonsActive; a++)
{
touchEvents.add(new TouchInfo());
}
}
In your initializeTouchDataListObject() method, you create tempTouchList and tempTimeList. Then, for EVERY TouchSet, you add these lists as their timeList and touchList. The problem here is that the two created lists are passed by REFERENCE, meaning that every single TouchSet has a reference to the two exact same lists. They all share the same lists and thus lists are changed for every TouchSet in every iteration.
You have 3 conditions. Add(temp) is in all 3.
1) a < b
2) a = b
3) a > c
I am creating a simple "Pairs" game in WPF. I have 12 Image controls on MainWindow. What I need to do, is to use OpenFileDialog to select multiple Images (can be less then all 6) and then randomly place them into Image controls. Each picture should appear twice. How would I be able to achieve this? I am stuck here for a while and only have following code at the moment. I am not asking for a solution, I only need a few pointers on how to deal with this. Thank you.
> public ObservableCollection<Image> GetImages()
{
OpenFileDialog dlg = new OpenFileDialog();
dlg.Multiselect = true;
ObservableCollection<Image> imagesList = new ObservableCollection<Image>();
if (dlg.ShowDialog() == true)
{
foreach (String img in dlg.FileNames)
{
Image image = new Image();
image.Name = "";
image.Location = img;
imagesList.Add(image);
}
}
return imagesList;
}
There are many ways to achieve your required results. A good way would be to use the Directory.GetFiles method, which will return a collection of string file paths:
string [] filePaths = Directory.GetFiles(targetDirectory);
You can then use a method to randomise the order of the collection. From the C# Shuffle Array page on DotNETPerls:
public string[] RandomizeStrings(string[] arr)
{
List<KeyValuePair<int, string>> list = new List<KeyValuePair<int, string>>();
// Add all strings from array
// Add new random int each time
foreach (string s in arr)
{
list.Add(new KeyValuePair<int, string>(_random.Next(), s));
}
// Sort the list by the random number
var sorted = from item in list
orderby item.Key
select item;
// Allocate new string array
string[] result = new string[arr.Length];
// Copy values to array
int index = 0;
foreach (KeyValuePair<int, string> pair in sorted)
{
result[index] = pair.Value;
index++;
}
// Return copied array
return result;
}
Then add your duplicate file paths, re-randomise the order again and populate your UI property with the items:
string[] filePathsToUse = new string[filePaths.Length * 2];
filePaths = RandomizeStrings(filePaths);
for (int count = 0; count < yourRequiredNumber; count++)
{
filePathsToUse.Add(filePaths(count));
filePathsToUse.Add(filePaths(count));
}
// Finally, randomize the collection again:
ObservableCollection<string> filePathsToBindTo = new
ObservableCollection<string>(RandomizeStrings(filePathsToUse));
Of course, you could also do it in many other ways, some easier to understand, some more efficient. Just pick a method that you feel comfortable with.
I can easily pass a data file to a 2D array if I know the size of the data file, but thats pretty pointless when you want to add and remove data.
How can I instantiate a 2D array of that Data rows length that is global and not out of scope to the rest of the program?
Here is the usual code, for an array of 4 rows and 6 columns, but I want to add/remove data to the data file making it of unknown length in rows.
string[,] allStudentData = new string[4, 6];
string[] allStudents = File.ReadAllLines("data.txt");
for (int i = 0; i < allStudents.Count(); i++)
{
for (int j = 0; j < 6; j++)
{
string[] DataIn = allStudents[i].Split(',');
allStudentData[i, j] = DataIn[j];
}
}
Thanks for your ideas :-)
Why not use something mutable, like a List ?
You can add columns using the .Add() command, , and you can collapse it into an array when you're done with it (.ToArray())
you can do as below
var result = File.ReadAllLines("data.txt").Select(x=>x.Split(',')).ToArray();
You can use a List that holds a custom object (it could be an array) instead of Array and then at the end convert the list to an array with the ToArray extension:
var list = new List<string[]>();
var data1 = new string[2] {"1", "2" };
var data2 = new string[3] {"1", "2", "3" };
list.Add(data1);
list.Add(data2);
list.ToArray(); // converts the list to string[][]
After you are done reading the file you could add easily more items to the list and then at the end write all modifications to the file. If you think, that in future you will need more than the two dimensional array, than it's worth it to create a custom object like:
public class Student
{
public string Name { get; set; }
public int Grade { get; set; }
}
and use this instead of the string[]:
var studentData = new List<Student>();
The maintenance later will be much more easier (adding address, classes, and so on). I admit, you will have a little more work to do when reading and writing, but if the project grows it will pay off.
You can still use LINQ to read the data on one line:
// creates a List<Student>
var studentData = File.ReadAllLines("data.txt")
.Select(row => row.Split(','))
.Select(elements =>
new Student
{
Name = elements[0],
Grade = int.Parse(elements[1])
}).ToList();
If the number of columns is always 6 and only the number of rows is unknown. Just change the first 2 rows of your code to:
string[] allStudents = File.ReadAllLines("data.txt");
string[,] allStudentData = new string[allStudents.Count(), 6];
If the number of columns is unknown you can do this to get a 2D result:
var not2DResult = File.ReadAllLines("data.txt").Select(x => x.Split(',')).ToArray();
var maxRow = not2DResult.Count()-1;
int maxColumn = Enumerable.Select(not2DResult, c => c.Count()).Max()-1;
var result2D = new string[maxRow, maxColumn];
for (int rowNumber = 0; rowNumber < maxRow; rowNumber++)
{
var row = not2DResult[rowNumber];
for (int columnNumber = 0; columnNumber < row.Count(); columnNumber++)
{
result2D[rowNumber, columnNumber] = row[columnNumber];
}
}
Try using a Lists to hold the file information.
var myList = new List<string>();
myList = File.ReadLines("data.txt");
var my2DList = new List<List<string>>();
foreach(string line in myList)
my2DList.Add(line.Split(','));
If you want to know the number of lines, just use:
int numberOfLines = my2DList.Count;
For the number of items in an individual line:
int lengthOfLine3 = my2DList[3].Length;